我无法理解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
示例输出如下:
添加1的结果添加的结果 在4个虚假结果中加1 添加2个FalseResult的FalseResult 添加3个假世界?的结果 加4错误
添加1个FalseResult of add的结果 in 2 False Result of add in 3 False 添加4 False的结果
添加1的结果添加的结果 在2个FalseResult中添加3个 FalseResult of add in 4 False
添加1的结果添加的结果 在2个FalseResult中添加3个 FalseResult of add in 4 False
添加1的结果添加的结果 在2个FalseResult中添加4个 FalseResult of add in 3 False
添加1的结果添加的结果 在4 FalseResult中添加2 FalseResult of add in 3 False
添加1个FalseResult of add的结果 4个虚假结果加2个假 添加3个错误的结果
添加1个FalseResult of add的结果 在4错误
添加2个FalseResult of add的结果 3错误
添加1个FalseResult of add的结果 在4错误
添加2个FalseResult of add的结果 in 3 False Result of add in 1 False 添加4 False的结果
添加2个FalseResult of add的结果 3错误
添加1个FalseResult of add的结果 在4错误
当我读到原子的时候
。这意味着事务内的所有操作都完全完成,没有任何其他线程修改我们的事务正在使用的变量,或者它失败,并且状态被回滚到事务开始之前的状态。简而言之,原子事务要么完全完成,要么就好像它们根本就不运行一样。
所以对于这个问题,在某些情况下succ的“返回”是否永远不会发生? 那就行了 succ&lt; - atomically $ runAdd d putStrLn $“加入的结果”++(show i)++“”++(show succ)
输出“加入的结果?i”(“好像它们根本没有运行”)
答案 0 :(得分: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
在您的情况下,交易将始终运行并始终完成。由于冲突,它可能在第二次或第三次尝试时完成,但是对于您(用户)来说这是不可见的。 STM确保动作以原子方式发生,即使在能够成功完成之前需要花费一些时间。
答案 1 :(得分:2)
threadDelay
已经返回(),之后无需明确return ()
newTVarIO
是atomically . newTVar
。forever
而不是像commandProcessor
中所做的那样使用尾部调用,则更具可读性。至于你的问题,答案是肯定的。它被称为live-lock,你的线程可以在其中工作,但它无法取得进展。想象一个非常昂贵的函数expensive
和一个非常便宜的函数cheap
。如果它们在同一atomically
上的竞争TVar
块中运行,则廉价函数可能导致expensive
函数永远不会完成。我为related SO question建立了一个示例。
你的结束例子并不完全正确,如果STM操作永远不会完成,那么永远不会到达putStrLn
,并且根本不会看到该线程的输出。