具有軟體事務記憶體的原子塊

Haskell 中另一個強大而成熟的併發工具是軟體事務記憶體,它允許多個執行緒以原子方式寫入 TVar a 型別的單個變數。

TVar a 是與 STM monad 相關的主要型別,代表事務變數。它們很像 MVar,但在 STM monad 中通過以下函式使用:

atomically::STM a -> IO a

原子地執行一系列 STM 動作。

readTVar::TVar a -> STM a

閱讀 TVar 的值,例如:

value <- readTVar t

writeTVar::TVar a -> a -> STM ()

給給定的 TVar 寫一個值。

t <- newTVar Nothing
writeTVar t (Just "Hello")

這個例子取自 Haskell Wiki:

import Control.Monad
import Control.Concurrent
import Control.Concurrent.STM
 
main = do 
  -- Initialise a new TVar
  shared <- atomically $ newTVar 0
  -- Read the value
  before <- atomRead shared
  putStrLn $ "Before: " ++ show before
  forkIO $ 25 `timesDo` (dispVar shared >> milliSleep 20)
  forkIO $ 10 `timesDo` (appV ((+) 2) shared >> milliSleep 50)
  forkIO $ 20 `timesDo` (appV pred shared >> milliSleep 25)
  milliSleep 800
  after <- atomRead shared
  putStrLn $ "After: " ++ show after
  where timesDo = replicateM_
       milliSleep = threadDelay . (*) 1000

atomRead = atomically . readTVar
dispVar x = atomRead x >>= print
appV fn x = atomically $ readTVar x >>= writeTVar x . fn