【问题标题】:Validation in STM transactions nested with orElse使用 orElse 嵌套的 STM 事务中的验证
【发布时间】:2014-01-17 18:44:19
【问题描述】:

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

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

例如我们在线程A:

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

假设A 正在执行嵌套事务takeTMVar b,另一个线程B 执行putTMVar a ();线程A 能否成功完成其嵌套事务,或者它是否无效(这会让我觉得错了)?

第二个点,我想我理解但不介意保证:在上面为A 描述的整个顶级事务被重试并最终阻塞的情况下,是当abc 中的任何一个发生变化时,A 会被唤醒,这是否正确?

最后作为奖励,如果我们(或库作者)将orElse 更改为infixr,是否会更改上述事务的语义?

【问题讨论】:

    标签: haskell concurrency ghc stm


    【解决方案1】:

    我不认为“嵌套”是描述这一点的正确术语。这是三个替代交易;没有一个嵌套在另一个中。特别是,这三者中的一者将发生并承诺——但哪一个发生并不确定。这句话应该足以回答所有三个问题,但为了确定起见,让我们为每个问题仔细说:

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

    2. 是的,没错:三个TMVars 都可以唤醒这个线程。

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

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

    【讨论】:

    • 我可能不明白你的观点1;要清楚我对TMVar 的使用只是我能想到的第一个示例,它是与retry 的简单事务(即,获取和放置的特定交互以及调用重试的内容并不重要)。在我的第一个问题中,我真正想要解决的是在不同TVars 上运行的不同线程中的子事务之间是否存在争用。如果这没有意义,我会在吃完东西后尝试澄清
    • “嵌套”也是链接评论中使用的语言
    • 哦,我明白你的意思了!所以我知道只有orElse 分支之一会成功;我想知道在A之后我们是否从第一个分支继续前进,另一个线程(B)可以通过触摸我们的TVar 使As 事务无效在第一个分支中使用
    • @jberryman 我添加了一些文字。希望这次我理解了你的问题。
    • 非常感谢,丹尼尔。最后一点,我不得不编写一个痛苦的测试程序来说服自己,但这似乎是正确的。我仍在努力解决它,但这对我来说确实是错误的行为:让orElse 的左右分支拥有相同的世界观有什么好处?替代品彼此完全隔离?我认为让分支单独成为原子将是一个更有用的属性。因为写几个orElses 很容易饿死。想法?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-09
    • 2018-06-18
    • 2014-08-21
    • 2017-02-22
    • 1970-01-01
    相关资源
    最近更新 更多