TVar如何运作?从我所看到的,它尝试在收到它们后立即运行所有事务,但是,事务完成使其他当前运行的事务无效,然后必须重新启动。这是TVar的工作原理吗?
如果是这种情况,如果每100ms发生1ms长的事务,这是否意味着需要200ms处理的事务永远不会完成?
答案 0 :(得分:8)
只要两个事务访问不同的TVars
,它们就可以同时提交而不会相互失效。
为了明确事务 无效时,让我们考虑以下情况:
t :: TVar Int
已初始化为0
,并在事务readTVar t
开头通过A
阅读。 B
,其中执行writeTVar t 1
。假设B
在A
之前提交。 STM系统将检查是否存在任何不一致,并断定B
此时提交是安全的,因此现在writeTVar t 1
生效。A
无效,因为在0
的开头读取了t
的旧值A
。 (如果允许A
提交,我们就会违反原子性。)关于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。