46

我已经看到 theTVar是一个简单的容器,而 theTMVar与 an 相同MVar,这意味着它有一个锁等,但在STMmonad 中。我想知道为什么有必要这样做,因为它的想法STM是使锁变得不必要。

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

4

2 回答 2

43

这不是真正的锁定问题,而是关于引用的含义:

  • TVar是 内的可变引用STM,表示一般共享状态。你创建它并持有一个值,你可以读取和写入它等等。它非常类似于IORefor STRef(无论如何它们都是一样的)。

  • TMVar是对线程可以用来通信的槽的引用。它可以创建为持有一个值,也可以为空。您可以将一个值放入其中,如果该值已被填充,则该值会阻塞,直到其他人将其清空;或者您可以从中获取一个值,如果该值已经为空,则在有人填充它之前会阻塞。它显然类似于MVar,但对于许多常见用途,将其视为用于通信生产者/消费者对的单元素队列可能更简单。

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

另请注意TChan,它大致实现为TVar链表中的两个 s 保存位置,其中每个前向链接也是一个TVar,并且用作通信的无界队列。

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

于 2011-08-02T16:20:59.807 回答
19

和之间的差异TVarTMVar没有看起来那么大——绝对不能与 和 之间的差异IORef相提并论MVar

虽然MVar确实为线程安全提供了一些锁定,TMVar但没有什么有趣的!(没有额外的锁定)所有重要的东西都已经用STMand实现了TVar,所以TMVar a它只是TVar (Maybe a)配备一些不错的功能的简写(其中一些阻止使用该retry功能)。

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

于 2011-08-03T00:38:50.363 回答