【发布时间】:2013-03-04 14:43:54
【问题描述】:
我发现 TVar 很容易使用,尽管 MVar 看起来更简单,而 TVar 功能更丰富。
所以我的问题很简单,我想去 MVar 而不是 TVar 的条件是什么?我想在不需要事务更新的任何时候,我可以使用 MVar,但这对我有什么好处?
【问题讨论】:
标签: haskell shared-memory stm
我发现 TVar 很容易使用,尽管 MVar 看起来更简单,而 TVar 功能更丰富。
所以我的问题很简单,我想去 MVar 而不是 TVar 的条件是什么?我想在不需要事务更新的任何时候,我可以使用 MVar,但这对我有什么好处?
【问题讨论】:
标签: haskell shared-memory stm
MVar
TVar 更快TVar
IORef
IO 写入/更新TVar
对于何时使用MVar 或TVar,并没有真正的硬性规定。
如果我保护的资源永远“丢失”(而不是空的,考虑Nothing 与Just mempty),那么MVar 通常是最有意义的。如果我需要对资源进行原子修改块,那么TVar 是最合适的。
【讨论】:
MVar,我会更清楚地说明这一点
MVar 拥有几种模式,例如:一些线程让其他线程占用(本质上是一个 1 元 FIFO 队列);许多线程在做modifyMVar 来修改一些共享状态;线程在进入临界区之前采用() 并在退出时替换(将其用作锁)等。
TVar 更安全但速度较慢。
MVar 可能会死锁,但效率要高得多。
更高效的仍然是IORef 和atomicModifyIORef (CAS),但是你可以用它做什么受到很大限制。
这确实是一种安全而不是性能的权衡。 TVars是完全通用的,非常安全。其他一切都不那么重要,而且规模越来越小。
【讨论】:
IORef 将是您最快的操作,但 GHC 7.8 对 MVar 进行了一些改进,将 takeMVar/putMVar 在几纳秒内read/writeIORef(比如我的机器上的 9.7/4.6 vs 3.7/7/3()),我们还有一个新的非常快的 readMVar(当然,当 MVar 已满时)。
atomicModifyIORef 在争用中的表现也很差,出于某种原因。
TVars 与modifyIORef 进行基准测试。我做了一些银行账户的事情,每个线程都会在两个银行账户之间进行交易。 IORef 的实现显然会出现不一致。我的第一次尝试使随机数生成器成为基准,而我的第二次尝试使一个更快的随机数生成器成为基准。在我的第三次尝试中,我得到了速度差异(~ 两倍快),我的随机生成器实际上根本不是随机的,而是从数组中获取预生成的数字。那时我意识到我不知道自己在做什么,所以我放弃了。