用orElse嵌套的STM事务中的验证

时间:2014-01-17 18:44:20

标签: haskell concurrency ghc stm

This commentary page描述了GHC中STM的许多细节,但我想澄清几点。

第一次,是否在父项中访问的变量发生更改时,嵌套事务无效?

例如我们在线程A

takeTMVar a `orElse` takeTMVar b `orElse` takeTMVar c

假设在A执行嵌套事务takeTMVar b时,另一个线程B执行putTMVar a ();可以线程A成功完成其嵌套事务,还是无效(这会让我觉得错误)?

第二点,我认为我理解但不介意再保证:在上面针对A描述的整个顶级事务被重试并最终阻止的情况下,如果Aab中的任何一个发生变化,c会被唤醒是否正确?

最后作为奖励,如果我们(或图书馆作者)将orElse更改为infixr,上述交易的语义是否会发生变化?

1 个答案:

答案 0 :(得分:5)

我不认为“嵌套”是描述这一点的正确术语。这是三个备用交易; none嵌套在另一个中。特别是,三者中的任何一个都将发生并被提交 - 但是哪一个发生并不是确定性的。这句话应该足以回答所有三个问题,但为了确保,让我们仔细说出每个问题:

  1. 无法保证。也许takeTMVar b将完成并提交;或者它可能会被抢占,takeTMVar a将被唤醒并完成。但他们不会同时完成,这是肯定的。

  2. 是的,这是正确的:所有三个TMVar都可以唤醒这个帖子。

  3. 语义不会改变:只要其中几个可以提交,最左边的那个就会。 (特别是,the paper describing STM说,“orElse函数遵循有用的法则:它是关联的,并且具有单位retry。”。)

  4. (来自评论中的问题)链接文件第8页上STM的语义确实可以保证最左边成功的事务 成功的事务。所以:如果线程A正在执行takeTMVar b(但尚未提交)并且线程B执行并提交写入a,那么之后不会发生任何其他事情,您可以确定将重新启动线程A并从a返回新写入的值。 “之后没有其他事情发生”部分很重要:语义对发生的事情作出承诺,而不是实现如何实现它;因此,如果另一个线程立即从a获取(以便takeTMvar a仍然是retry),则允许一个足够聪明的实现注意到这一点,而不是重新启动线程{{ 1}}从交易开始。