试图理解Haskell STM简单的事情

Jon*_*nke 3 haskell transactional-memory ghc

我无法理解STM中原子的概念.

我用一个例子说明

import Control.Concurrent
import Control.Concurrent.STM
import Control.Monad
import qualified Data.Map as Map 

main :: IO ()
main =  do
    d <- atomically$ newTVar Map.empty
    sockHandler  d 

sockHandler ::  TVar (Map.Map String Int)-> IO ()
sockHandler  d = do
    forkIO $ commandProcessor  d 1
    forkIO $ commandProcessor  d 2
    forkIO $ commandProcessor  d 3
    forkIO $ commandProcessor  d 4
    forkIO (threadDelay 1000 >> putStrLn "Hello World?")

    threadDelay 10000
    return ()

commandProcessor ::  TVar (Map.Map String Int)-> Int-> IO ()
commandProcessor  d i= do
  addCommand d i
  commandProcessor  d i 

addCommand  ::  TVar (Map.Map String Int) ->Int -> IO ()
addCommand    d i = do
  succ <- atomically $ runAdd d
  putStrLn  $"Result of add in " ++ (show i)++ " " ++( show succ)

runAdd  d =do
  dl <- readTVar d
  let (succ,g)= if   Map.member "a" dl
                  then
                      (False,dl)
                  else
                      (True,Map.insert "a" 9 dl)
  writeTVar d g
  return succ
Run Code Online (Sandbox Code Playgroud)

示例输出如下:

加入的结果1加入4的真实结果加入的结果为1加入的FalseResult加入2的FalseResult加入3个错误的Hello World?加4的结果为假

加入1的FalseResult加2的结果错误加3的结果错误加4的结果错误

添加的结果1添加的假结果2添加的FalseResult 3添加的FalseResult False

添加的结果1添加的假结果2添加的FalseResult 3添加的FalseResult False

添加的结果1添加的假结果2添加的FalseResult 4添加的FalseResult False

加1的结果加入4的FalseResult加2的FalseResult加3的FalseResult

添加1的FalseResult添加的结果4 False结果添加2 False结果添加3 False

添加的结果1 FalseResult of add in 4 False

添加的结果2 FalseResult of add in 3 False

添加的结果1 FalseResult of add in 4 False

添加的结果2个FalseResult of add in 3 False结果添加1个False结果添加4个False

添加的结果2 FalseResult of add in 3 False

添加的结果1 FalseResult of add in 4 False

当我读到原子的时候

.这意味着事务内的所有操作都完全完成,没有任何其他线程修改我们的事务正在使用的变量,或者它失败,并且状态被回滚到事务开始之前的状态.简而言之,原子事务要么完全完成,要么就好像它们根本就不运行一样.

所以对于这个问题,在某些情况下succ的"返回"是否永远不会发生?那就是行succ < - atomically $ runAdd d putStrLn $"添加的结果"++(show i)++""++(show succ)

给出"加入的结果?i"的输出("好像它们从未运行过")

Nei*_*own 7

如果事务确实被回滚,那么会发生什么是您的程序再次尝试.你可以想象实现是atomically这样的:

atomically action = do varState <- getStateOfTVars
                       (newState, ret) <- runTransactionWith action varState
                       success <- attemptToCommitChangesToTVars newState
                       if success
                         then return ret
                         else atomically action -- try again
Run Code Online (Sandbox Code Playgroud)

在您的情况下,交易将始终运行并始终完成.由于冲突,它可能在第二次或第三次尝试时完成,但是对于您(用户)来说这是不可见的.STM确保动作以原子方式发生,即使在能够成功完成之前需要花费一些时间.