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

jbe*_*man 5 concurrency haskell ghc stm

这篇评论页面描述了STMGHC 的许多细节,但我想澄清几点.

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

例如我们有线程A:

takeTMVar a `orElse` takeTMVar b `orElse` takeTMVar c
Run Code Online (Sandbox Code Playgroud)

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

一个第二点,我想我明白,但是,也不会介意的保证:在上述用于整个顶层事务的情况下A重试和finally块,是纠正A会被唤醒时,任何的a,bc改变?

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

Dan*_*ner 5

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

  1. 没有保证.也许takeTMVar b会完成并承诺; 或者它可能会被抢先一步,并且takeTMVar a会被唤醒并完成.但他们不会同时完成,这是肯定的.

  2. 是的,这是正确的:所有三个人TMVar都可以唤醒这个线程.

  3. 语义不会改变:只要其中几个可以提交,最左边的一个就会改变.(特别是,描述STM的论文称,"该orElse函数遵循有用的法则:它是关联的,并且具有单位retry.".)

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