TVar和TMVar之间的区别

Lan*_*nbo 43 concurrency haskell stm

我已经看到它TVar是一个简单的容器,而它TMVar是一个MVar,意思是它有一个锁等,但在STMmonad中.我想知道为什么这是必要的,因为想法STM是不需要锁.

那么,如果你有一个类似于[Handle]你想要在线程之间使用的套接字句柄列表的类型,那么哪个是使用的forkIO

C. *_*ann 43

这不是锁定的问题,而是关于引用意味着什么:

  • TVar是一个可变的引用STM,代表一般的共享状态.你创建它持有一个值,你可以读取和写入它等.它非常类似于IORefSTRef(无论如何都是相同的).

  • TMVar是对线程可用于通信的插槽的引用.它可以创建一个值,也可以为空.你可以在其中放入一个值,如果已经填充了块,直到有人将其清空; 或者你可以从中获取一个值,如果已经是空块,直到有人填充它.它显然类似于a MVar,但对于许多常见用途而言,将其视为用于通信生产者/消费者对的单元素队列可能更简单.

简而言之,TVar是一般共享状态,如果您希望从任意位置对数据进行原子更新,请使用它.TMVar是一个同步原语,如果你想让一个线程等到某个东西变得可用,就可以使用它,而另一个则等待需要的东西.

还要注意TChan,它大致实现为TVar链表中的两个保持位置,其中每个前向链路也是a TVar,并且用作通信的无界队列.

所有这些都可以以稍微不同的方式使用 - 当然 - 你可以在TMVar不删除它的情况下查看a的值,例如,如果你想要一个场景,其中多个线程都等待单个资源变得可用,但它永远不会"用完了".


Rot*_*sor 19

之间的差异TVar,并TMVar没有那么大,因为他们看-绝对没有可比性之间的差异IORefMVar.

虽然MVar确实为线程安全提供了一些锁定,TMVar但没有什么有趣的!(没有额外的锁)一切都重要的是已经在执行STMTVar,所以TMVar a只是一个短手TVar (Maybe a)配备了一些不错的功能(其中使用块的一些retry功能).

阻塞retry是否符合其精神STM以及它是否消除了STM的一些优势(没有死锁等)是一个单独的问题,我希望看到有更有经验的人来回答它.

  • 虽然它不会在事务中间死锁,但是可以创建永远不会以类似于创建传统死锁的方式成功的事务,例如两个等待彼此结果的事务.在实践中,这与死锁的区别并不是很明显. (6认同)
  • 啊,对.我认为实际上这个术语恰当地说就是"活锁".尽管如此,它更像是一种资源匮乏而不是僵局.虽然死锁很容易因相同资源的无关使用而导致,但我认为STM的乐观性质使得活锁不太可能,除非存在直接冲突或非常高的整体争用. (4认同)