Another powerful & mature concurrency tool in Haskell is Software Transactional Memory, which allows for multiple threads to write to a single variable of type TVar a
in an atomic manner.
TVar a
is the main type associated with the STM
monad and stands for transactional variable. They're used much like MVar
but within the STM
monad through the following functions:
atomically :: STM a -> IO a
Perform a series of STM actions atomically.
readTVar :: TVar a -> STM a
Read the TVar
's value, e.g.:
value <- readTVar t
writeTVar :: TVar a -> a -> STM ()
Write a value to the given TVar
.
t <- newTVar Nothing writeTVar t (Just "Hello")
This example is taken from the 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