【问题标题】:Does reading a TChan result in blocking or polling?读取 Tchan 会导致阻塞或轮询吗?
【发布时间】:2013-01-27 07:38:16
【问题描述】:

首先,一些背景。我想要一个队列,我想以两种不同模式之一操作。在第一种模式中,如果队列中存在一个元素,我希望能够检索一个元素,但如果没有元素,则 not 阻止。在第二种模式下,我希望能够阻塞直到队列有一个元素。 (我知道我可以为每种模式使用专门的机制,但我想排除一些通用代码,因此如果我可以对两种操作模式使用相同的机制,那将是最简单的。)

我可以使用Chan,但根据文档,我不应该使用isEmptyChan,因为它可能会出现死锁,因此不推荐使用。这给我留下了TChan。 tryReadTChan 函数为我提供了我想要的第一种模式(即我可以检查元素是否存在而不阻塞),但我不确定 readTChan 究竟做了什么。我的心理模型是atomically 块将不断重试,直到通道中出现一个元素,这意味着它会忙于循环浪费 CPU 周期;这与 readChan(即非 STM 版本)不同,后者(如果我理解正确的话)实际上会阻塞线程的执行,直到元素可用,因为运行时线程调度程序可以理解 MVar。

TChan 和Chan 一样,如果我使用readTChan,运行时足够聪明,不会在值可用之前调度调用线程?还是会浪费大量的 CPU 周期不断轮询一个值到达?

【问题讨论】:

    标签: haskell ghc stm


    【解决方案1】:

    STM 阻塞(通过retry)的行为就像它立即重试事务一样,但实现更智能:由于 STM 会跟踪您在事务进行时读取的变量,因此它知道事务将执行只要这些变量具有相同的值,方法相同。因此,当事务失败时,它会阻塞(实际上不会重试),直到您使用的变量之一发生更改。对于TChans,这意味着它会阻塞直到有人写信给TChan。

    我推荐 Simon Marlow 在并发和并行 Haskell 上的 slides 以很好地介绍 STM(以及其他内容)。

    【讨论】:

    • 太棒了!非常感谢,特别是演讲的链接!
    【解决方案2】:

    您的心智模型具有正确的指称语义,但错过了 STM 进行的操作优化。当一个事务在 STM 中重试时,它会阻塞直到它从重试更改之前读取的一些 TVar。 (是的,TChan 是根据TVar 实现的。)

    因此,执行事务与事务不断重试具有相同的含义 - 但 STM 系统足够智能,不会在事务中发生不同情况的情况下不忙循环。

    【讨论】:

      猜你喜欢
      • 2023-03-15
      • 1970-01-01
      • 1970-01-01
      • 2014-02-05
      • 1970-01-01
      • 2016-11-14
      • 1970-01-01
      • 1970-01-01
      • 2011-12-01
      相关资源
      最近更新 更多