Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 与orElse嵌套的STM事务中的验证_Haskell_Concurrency_Ghc_Stm - Fatal编程技术网

Haskell 与orElse嵌套的STM事务中的验证

Haskell 与orElse嵌套的STM事务中的验证,haskell,concurrency,ghc,stm,Haskell,Concurrency,Ghc,Stm,在GHC中描述了许多关于STM的详细信息,但我想澄清几点 首先,当父事务中访问的变量发生更改时,嵌套事务是否无效 例如,我们在线程中有一个: takeTMVar a `orElse` takeTMVar b `orElse` takeTMVar c 假设A正在执行嵌套事务takeTMVar b,另一个线程b执行putTMVar A();线程A能否成功完成其嵌套事务,或者它是否已失效(我认为这是错误的) 第二点,我想我理解,但我不介意再次保证:如果上面描述的A的整个顶级事务被重试并最终阻塞,那么

在GHC中描述了许多关于
STM
的详细信息,但我想澄清几点

首先,当父事务中访问的变量发生更改时,嵌套事务是否无效

例如,我们在线程
中有一个

takeTMVar a `orElse` takeTMVar b `orElse` takeTMVar c
假设
A
正在执行嵌套事务
takeTMVar b
,另一个线程
b
执行
putTMVar A()
;线程
A
能否成功完成其嵌套事务,或者它是否已失效(我认为这是错误的)

第二点,我想我理解,但我不介意再次保证:如果上面描述的
A
的整个顶级事务被重试并最终阻塞,那么当
A
b
c
中的任何一个发生更改时,
A
将被唤醒,这是否正确

最后,如果我们(或库作者)将
orElse
更改为
infixr

我不认为“嵌套”是描述这一点的正确术语,那么上述事务的语义是否会发生更改。这是三种替代交易;没有一个嵌套在另一个中。特别是,这三种情况中有一种将要发生并被实施——但哪种情况发生并不确定。这一句话应该足以回答所有三个问题,但可以肯定的是,让我们仔细地对每一个问题说:

  • 没有保证。可能
    takeTMVar b
    将完成并提交;或者它可能会被抢先,并且
    takeTMVar a
    将被唤醒并完成。但它们不会同时完成,这是肯定的

  • 是的,这是正确的:所有三个
    TMVar
    s都可以唤醒这个线程

  • 语义不会改变:只要其中几个可以提交,最左边的一个就会提交。(特别是说,“
    orElse
    函数遵循有用的规则:它是关联的,具有单元
    重试
    ”。)

  • (从你在评论中的问题来看)链接文章第8页的STM语义确实保证了最左边成功的交易就是成功的交易。因此:如果线程
    A
    正在执行
    takeTMVar b
    (但尚未提交),并且线程
    b
    执行并提交对
    A
    的写入,并且之后没有发生任何其他事情,则可以确保线程
    A
    将重新启动并从
    A
    返回新写入的值。“之后什么也不发生”部分很重要:语义承诺发生什么,但不承诺实现如何实现它;因此,如果,比如说,另一个线程立即从
    a
    中获取(因此
    takeTMvar a
    仍将进行
    重试
    ),那么一个足够聪明的实现可以注意到这一点,而不会从事务开始重新启动线程
    a


  • 我可能不明白你的第一点;明确地说,我使用的
    TMVar
    只是我能想到的第一个例子,这是一个简单的事务,其中包含
    retry
    (即,take和put的具体交互以及什么调用retry并不重要)。在我的第一个问题中,我真正想了解的是,在不同的
    TVars
    上运行的不同线程中,子事务之间是否存在争用。如果这不合理,我会在吃了东西后再澄清链接评论中使用的语言也是嵌套的哦,我明白你的意思了!因此,我知道只有一个
    orElse
    分支会成功;我想知道在
    A
    中,在我们从第一个分支继续之后,另一个线程(
    B
    )是否可以通过触摸我们在第一个分支中使用的
    TVar
    使
    A
    事务无效branch@jberryman我添加了一些文本。希望这次我能理解你的问题。谢谢你,丹尼尔。在最后一点上,我不得不写一个痛苦的测试程序来说服自己,但这似乎是正确的。我仍在试图把我的头绕在它周围,但这在我看来确实是一种错误的行为:
    orElse
    的左分支和右分支拥有相同的世界观有什么好处,因为它们之间是完全孤立的?我认为,将分支单独作为原子将是一个更有用的特性。就像现在一样,通过编写一些
    orElse
    s,就很容易挨饿。思想?