Haskell:TVar是如何工作的?

时间:2012-04-10 16:27:39

标签: haskell concurrency tvar

TVar如何运作?从我所看到的,它尝试在收到它们后立即运行所有事务,但是,事务完成使其他当前运行的事务无效,然后必须重新启动。这是TVar的工作原理吗?

如果是这种情况,如果每100ms发生1ms长的事务,这是否意味着需要200ms处理的事务永远不会完成?

2 个答案:

答案 0 :(得分:8)

只要两个事务访问不同的TVars,它们就可以同时提交而不会相互失效。

为了明确事务 无效时,让我们考虑以下情况:

  1. 假设t :: TVar Int已初始化为0,并在事务readTVar t开头通过A阅读。
  2. 同时,在另一个线程中,启动事务B,其中执行writeTVar t 1。假设BA之前提交。 STM系统将检查是否存在任何不一致,并断定B此时提交是安全的,因此现在writeTVar t 1生效。
  3. 但是,这导致事务A无效,因为在0的开头读取了t的旧值A。 (如果允许A提交,我们就会违反原子性。)
  4. 关于Haskell的STM系统的原始论文[1](见第6.5节)回答了你的问题:

      

    “饥饿是可能的。例如,运行的事务   很长一段时间可能会反复与较短的交易冲突。   我们认为饥饿不太可能在实践中发生,但我们   没有进一步的经验就无法分辨。“

    [1] Tim Harris,Simon Marlow,Simon Peyton Jones和Maurice Herlihy。 ACM 2005年并行编程原理与实践会议(PPoPP'05)。

答案 1 :(得分:5)

  

如果每100ms发生1ms长的事务,这是否意味着需要200ms处理的事务永远不会完成?

如果事务触及相同的TVar,则只会发生冲突,因此,如果某些1ms事务避免了受200ms事务影响的所有变量,那么200ms就可以完成。此外,由于STM monad对内部允许的内容(内存访问和纯计算!)非常严格,因此在这两者之间存在这种差异是非常不寻常的。交易时间;通常,它们只有几个内存读/写长,所有IO和其他计算都将在事务之外完成。此外,特定事务是否永远被其他事务阻止是一个调度问题;我并非100%确定GHC当前的调度程序是什么样的,但似乎有理由认为它优先考虑旧的(或更高的故障率)交易。

也就是说,livelock是STM的一个非常现实的问题,并且在更传统的锁定并发实现中就像僵局一样难以理解为死锁。

  

TVar如何运作?

您可能会喜欢this paper