TVar是如何工作的?据我所知,它试图在收到所有事务后立即运行它们,然而,一个完成的事务会使其他当前正在运行的事务无效,然后这些事务必须重新启动。这是TVar的工作方式吗?
如果是这种情况,如果有1ms长的事务每100ms发生一次,这是否意味着花费200ms来处理的事务永远不会完成?
发布于 2012-04-11 00:57:30
只要两个事务访问不同的TVars,就可以同时提交它们,而不会使彼此无效。
为了清楚说明事务何时失效,让我们考虑以下场景:
t :: TVar Int被初始化为0,并在事务A开始时通过readTVar t读取。B,其中执行writeTVar t 1。假设B在A之前提交。STM系统将检查是否存在任何不一致,并得出结论认为在这一点上B提交是安全的,因此现在writeTVar t 1变为effective.A无效,因为0的旧值t是在A开始时读取的。(如果允许A提交,我们将违反原子性。) 关于Haskell的STM系统的原始论文1(参见第6.5节)回答了您的问题:
“饥饿是可能的。例如,一个运行了很长时间的事务可能会反复与较短的事务发生冲突。我们认为饥饿在实践中不太可能发生,但我们在没有进一步经验的情况下无法判断。”
1蒂姆·哈里斯、西蒙·马洛、西蒙·佩顿·琼斯和莫里斯·赫利希。ACM并行编程原理与实践会议2005 (PPoPP'05)。
发布于 2012-04-11 00:59:54
如果有1ms长的事务每100ms发生一次,这是否意味着花费200ms处理的事务永远不会完成?
事务只有在接触到相同的TVar时才会冲突,因此如果1ms事务中的一些事务避免了受200ms事务影响的所有变量,那么200ms事务将能够完成。此外,由于STM monad对内部允许的内容非常严格(只允许内存访问和纯计算!)事务长度之间存在这样的差异是非常不寻常的;通常,它们只有几个内存读/写长度,并且所有的IO和其他计算都将在事务之外完成。此外,某个特定事务是否会永远被其他事务阻塞是一个调度问题;我不能100%确定GHC当前的调度器是什么样子,但它似乎更倾向于较旧(或失败率更高)的事务。
这就是说,活锁是STM的一个非常现实的问题,在更传统的锁并发实现中,活锁与死锁一样隐蔽,也很难解释。
TVar是如何工作的?
你可能会喜欢这篇文章:
https://stackoverflow.com/questions/10092655
复制相似问题