繁体   English   中英

Haskell:TVar是如何工作的?

[英]Haskell: How does TVar work?

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

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

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

为了弄清楚交易何时无效,让我们考虑以下场景:

  1. 假设t:: TVar Int初始化为0 ,并在事务A的开始通过readTVar t读取。
  2. 同时,在另一个线程中,启动事务B ,其中执行writeTVar t 1 假设BA之前提交。 STM系统会检查是否有不一致,并断定B此时commit是安全的,所以现在writeTVar t 1生效。
  3. 但是,这会导致事务A无效,因为在A的开头读取了t的旧值0 (如果允许A提交,我们就会违反原子性。)

关于 Haskell 的 STM 系统的原始论文 [1](参见第 6.5 节)回答了您的问题:

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

[1] 蒂姆·哈里斯、西蒙·马洛、西蒙·佩顿·琼斯和莫里斯·赫利希。 ACM 并行编程原则与实践会议 2005 (PPoPP'05)。

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

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

也就是说,活锁是STM的一个非常现实的问题,并且在更传统的锁定并发实现中与死锁一样隐蔽且难以推理。

TVar 是如何工作的?

您可能会喜欢这篇论文:

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM