3

我一直在理解 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 True 添加结果 4 False 添加结果 1 False 结果添加 2 FalseResult 添加 3 False Hello World?添加的结果 4 False

add in 1 的结果 False add in 2 的结果 False add in 3 的结果 False add in 4 的结果 False

add in 1 的结果 False add in 2 的结果 False add in 3 的结果 False add in 4 的结果 False

add in 1 的结果 False add in 2 的结果 False add in 3 的结果 False add in 4 的结果 False

add in 1 的结果 False add in 2 的结果 False add in 4 的结果 False add in 3 的结果 False

add in 1 的结果 False add in 4 的结果 False add in 2 的结果 False add in 3 的结果 False

add in 1 的结果 False add in 4 的结果 False add in 2 的结果 False add in 3 的结果 False

add in 1 False 结果 add in 4 False

add in 2 False 结果 add in 3 False

add in 1 False 结果 add in 4 False

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

add in 2 False 结果 add in 3 False

add in 1 False 结果 add in 4 False

当我读到原子

. 这意味着事务中的所有操作完全完成,没有任何其他线程修改我们的事务正在使用的变量,否则它会失败,并且状态会回滚到事务开始之前的位置。简而言之,原子事务要么完全完成,要么就好像它们从未运行过一样。

那么对于这个问题,在某些情况下,成功的“回归”可能永远不会发生吗?那可以是 succ <- atomically $ runAdd d putStrLn $"Result of add in " ++ (show i)++ " " ++( show succ)

给出“添加结果?i”的输出(“好像它们根本没有运行”)

4

2 回答 2

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 确保动作以原子方式发生,即使它需要一些时间才能成功地做到这一点。

于 2011-02-02T09:27:53.477 回答
2
  1. threadDelayreturn ()已经返回(),之后不需要显式
  2. newTVarIO是 的简明版本atomically . newTVar
  3. 如果您使用forever而不是像在commandProcessor.

至于你的问题,答案是“是”。它被称为活锁,您的线程有工作要做,但它无法取得进展。想象一个非常昂贵的函数,expensive和一个非常便宜的函数,cheap。如果它们在相同的竞争atomically块中运行,TVar那么廉价功能可能会导致该expensive功能永远无法完成。我为相关的 SO question构建了一个示例。

但是,您的结束示例并不完全正确,如果 STM 操作从未​​完成,putStrLn则将永远无法到达,并且该线程根本看不到任何输出。

于 2011-02-03T01:15:04.447 回答