This commentary page在GHC中描述了STM的许多详细信息,但我想在几点上保持清晰。

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

例如我们在A线程中:

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

假设A执行嵌套事务takeTMVar b时,另一个线程B执行了putTMVar a ();线程A是否可以成功完成其嵌套事务,或者它是否无效(这会使我感到错误)?

我认为我理解但不介意的第二个点:在重试并最终阻止了上述针对A的整个顶级交易的情况下,是否正确,当A中的任何一个被唤醒时,a是否正确,bc更改?

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

最佳答案

我不认为“嵌套”是描述此词的正确术语。这是三个备用交易;没有一个嵌套在另一个内部。特别是,这三种情况中的一种恰好会发生并被落实-但是发生的哪一种并不确定。这句话足以回答所有三个问题,但是为确保确定,让我们为每个问题仔细说一下:

  • 无法保证。也许takeTMVar b将完成并提交;否则它将被抢占并且takeTMVar a将被唤醒并完成。但是他们不会全部完成,这是肯定的。
  • 是的,这是正确的:所有三个TMVar都可以唤醒该线程。
  • 语义不会改变:只要可以提交其中的几个,最左边的一个就会提交。 (特别是the paper describing STM说:“orElse函数遵循有用的规律:它是关联的,并且具有retry单位。”。)
  • (来自评论中的问题)链接文件第8页STM的语义确实确实确保最成功的事务是成功的事务。因此:如果线程A正在执行takeTMVar b(但尚未提交),并且线程B已执行并提交对a的写操作,此后再无其他 react ,则可以确保线程A将重新启动并从a返回新写入的值。 “此后什么都没有发生”部分很重要:语义保证会发生什么,但不能保证实现是如何实现的;因此,例如,如果另一个线程立即从a夺走(以便takeTMvar a仍将到达retry),则允许足够聪明的实现来注意到这一点,而不是从事务开始时重新启动线程A
  • 10-06 13:45
    查看更多