何时/为什么在TVar上使用MVar

Jim*_*ffa 36 haskell shared-memory stm

我觉得TVar很容易使用,即使MVar看起来更简单一些,而TVar更有特色.

所以我的问题很简单,我想要什么条件去MVar而不是TVar?我想任何时候我都不需要事务更新我可以使用一个MVar,但这对我有什么好处?

Don*_*art 36

电视更安全但速度更慢.

MVars可以死锁,但效率更高.

更高效的仍然是IORefatomicModifyIORef(CAS),但那是在高度,你可以用它做什么限制.

这实际上是对性能权衡的安全性.TVars非常通用,非常安全.其他一切都不那么严重,规模越来越小.

  • 任何人都可以量化实际的速度差异吗?(据推测,这很难测量,因为它取决于实际的线程交互......) (4认同)
  • @MathematicalOrchid忽略了并发问题:读取和编写`IORef`将是你最快的操作,但是GHC 7.8附带了一些改进'MVar`,它将`takeMVar/putMVar`带到了`read/writeIORef`的几ns内(在我的机器上说9.7/4.6 vs 3.7/7/3(<关于谎言和基准的通常免责声明>))我们也有一个新的非常快的`readMVar`(当MVar充满当然). (2认同)
  • @MathematicalOrchid我曾试图将'TVars`与`modifyIORef`作为基准.我做了一些银行账户,线程会在两个银行账户之间进行交易."IORef"实施最终会出现不一致的情况.我的第一次尝试设法为一个随机数发生器做准备,而我的第二次尝试则是一个更快的随机发生器.在我的第三次尝试中,我得到了一个速度差异(〜快两倍),我的随机发生器实际上根本不是随机的,只是从阵列中获取预生成的数字.那时我意识到我不知道自己在做什么所以我放弃了. (2认同)

cdk*_*cdk 36

无功

  • 可以是空的
  • 用于实现线程之间的同步模式
  • 允许线程之间的单向通信
  • TVar某些情况下更快

的TVar

  • 不能为空
  • 原子交易
  • 线程之间的"共享内存"; 例如,可以用于实现多个线程可以读/写的查找缓存
  • access是事务日志中操作数的线性时间
  • 如果存在许多较短的事务,则长时间运行的事务很容易受到饥饿,从而阻止它们成功提交

IOREF

  • 可变指针式引用
  • 经常用于破坏性IO写入/更新
  • 具有原子CAS操作,但复杂的事务逻辑更适合于a TVar

什么时候使用MVar或没有真正的硬性规则TVar.如果我正在守卫的资源将"失踪"(而不是空,考虑Nothingvs Just mempty),那么MVar通常是最有意义的.如果我需要对资源执行原子块修改,那么TVar最合适.

  • 可能也想添加关于饥饿的说明.MVars保证公平,TVars不公平. (4认同)
  • 你指的是共享的MVar用于线程通信,它们不应该只用于单向通信,因为如果两个线程都在更新相同的MVar来回交谈它们会有竞争条件吗? (2认同)
  • @JimmyHoffa你可以使用`MVar`拥有几个模式,例如:一些线程让其他人服用(基本上是1-ary FIFO队列); 许多线程做`modifyMVar`来修改一些共享状态; 线程在进入临界区之前采用`()`并在退出时替换(使用它作为锁)等. (2认同)