STMとロックについて
だいぶん間が開いてしまいましたが、その3です。
STMモナドによる操作は、ロックフリーです。 synchronize だとか lock だとか unlock だとかいうキーワードを書く必要はありません。 しかし、それは Haskell のコードからの視点のようです。 内部的にはロックを使っています。 そこで、ロックを実感するために、このようなコードを実行してみます。 import宣言と、ここにない関数はその1、その2から持ってきてください。
fib :: Int -> Int fib 0 = 0 fib 1 = 1 fib n = fib (n - 1) + fib (n - 2) threadA :: TVar Int -> IO () threadA v = do n <- atomically $ readTVar v print n atomically $ writeTVar v (n + 1) threadB :: TVar Int -> IO () threadB v = atomically $ writeTVar v $ fib 40 main :: IO () main = do c <- newCounter v <- newTVarIO 0 fork c $ every 500 $ threadA v fork c $ threadB v waitCounter c 2
fib は有名なフィボナッチ数列です。 時間がかからないと意味がないので、わざと遅い実装にしています。 threadA は fib 40 を計算して、2つのスレッドで共有している変数 v に結果を代入しています。 threadB は v の値を出力して v を1増やしています。
このコードを実行すると、
0 1 2 (中略) 102334155 102334156 102334157
このような結果が期待されます。 しかし、このような結果にはなりません。 実際には、