具有软件事务内存的原子块

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