This commentary page在GHC中描述了STM
的许多详细信息,但我想在几点上保持清晰。
首先,当父级中访问的变量发生更改时,嵌套事务是否无效?
例如我们在A
线程中:
takeTMVar a `orElse` takeTMVar b `orElse` takeTMVar c
假设
A
执行嵌套事务takeTMVar b
时,另一个线程B
执行了putTMVar a ()
;线程A
是否可以成功完成其嵌套事务,或者它是否无效(这会使我感到错误)?我认为我理解但不介意的第二个点:在重试并最终阻止了上述针对
A
的整个顶级交易的情况下,是否正确,当A
中的任何一个被唤醒时,a
是否正确,b
或c
更改?最后,作为红利,如果我们(或库作者)将
orElse
更改为infixr
,上述交易的语义是否会发生变化? 最佳答案
我不认为“嵌套”是描述此词的正确术语。这是三个备用交易;没有一个嵌套在另一个内部。特别是,这三种情况中的一种恰好会发生并被落实-但是发生的哪一种并不确定。这句话足以回答所有三个问题,但是为确保确定,让我们为每个问题仔细说一下:
takeTMVar b
将完成并提交;否则它将被抢占并且takeTMVar a
将被唤醒并完成。但是他们不会全部完成,这是肯定的。 TMVar
都可以唤醒该线程。 orElse
函数遵循有用的规律:它是关联的,并且具有retry
单位。”。)A
正在执行takeTMVar b
(但尚未提交),并且线程B
已执行并提交对a
的写操作,此后再无其他 react ,则可以确保线程A
将重新启动并从a
返回新写入的值。 “此后什么都没有发生”部分很重要:语义保证会发生什么,但不能保证实现是如何实现的;因此,例如,如果另一个线程立即从a
夺走(以便takeTMvar a
仍将到达retry
),则允许足够聪明的实现来注意到这一点,而不是从事务开始时重新启动线程A
。