首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >试图理解Haskell STM简单的事情

试图理解Haskell STM简单的事情
EN

Stack Overflow用户
提问于 2011-02-02 08:56:52
回答 2查看 1.8K关注 0票数 3

我被困于理解STM中原子化的概念。

我用一个例子来说明

代码语言:javascript
复制
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 FalseResult加2 FalseResult加3假你好世界?加4错的结果

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

加1假结果加在2 FalseResult中加3 FalseResult加4假

加1假结果加在2 FalseResult中加3 FalseResult加4假

加1假结果加在2 FalseResult中加4 FalseResult加3假

加1假结果加在4 FalseResult中加2 FalseResult加3假

加1 FalseResult加4假结果加2假结果加3假结果

加1 FalseResult加4假的结果

添加2 FalseResult的结果加3错

加1 FalseResult加4假的结果

加法2 FalseResult的结果加3假结果加1假结果加4假

添加2 FalseResult的结果加3错

加1 FalseResult加4假的结果

当我从原子上读到

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

因此,对于这个问题,succ在某些情况下会不会“回归”呢?即行succ <-原子化$ runAdd d putStrLn $“添加”++ ( show i)++“++ ( show )”的结果。

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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-02-02 09:27:53

如果一个事务确实被回滚,那么您的程序将再次尝试。您可以想象atomically的实现如下所示:

代码语言:javascript
复制
atomically action = do varState <- getStateOfTVars
                       (newState, ret) <- runTransactionWith action varState
                       success <- attemptToCommitChangesToTVars newState
                       if success
                         then return ret
                         else atomically action -- try again

在您的情况下,事务将始终运行并始终完成。由于冲突,它可能在第二次或第三次尝试时完成,但对于用户来说,这是不可见的。STM要确保操作是原子性的,即使在它能够成功地做到这一点之前只需要几步就可以了。

票数 7
EN

Stack Overflow用户

发布于 2011-02-03 01:15:04

  1. threadDelay已经返回(),不需要显式地使用return () afterward
  2. newTVarIO是一个简洁的atomically . newTVar.
  3. It's版本,如果您使用forever而不是像在commandProcessor.

中那样调用自己

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

但是,如果STM操作始终未完成,则永远不会到达putStrLn,也不会从该线程看到任何输出。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4872411

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档