我已经看到 theTVar
是一个简单的容器,而 theTMVar
与 an 相同MVar
,这意味着它有一个锁等,但在STM
monad 中。我想知道为什么有必要这样做,因为它的想法STM
是使锁变得不必要。
那么,如果你说有一个类型,比如[Handle]
你想在线程之间使用的套接字句柄列表,那么使用forkIO
哪个?
我已经看到 theTVar
是一个简单的容器,而 theTMVar
与 an 相同MVar
,这意味着它有一个锁等,但在STM
monad 中。我想知道为什么有必要这样做,因为它的想法STM
是使锁变得不必要。
那么,如果你说有一个类型,比如[Handle]
你想在线程之间使用的套接字句柄列表,那么使用forkIO
哪个?
这不是真正的锁定问题,而是关于引用的含义:
TVar
是 内的可变引用STM
,表示一般共享状态。你创建它并持有一个值,你可以读取和写入它等等。它非常类似于IORef
or STRef
(无论如何它们都是一样的)。
TMVar
是对线程可以用来通信的槽的引用。它可以创建为持有一个值,也可以为空。您可以将一个值放入其中,如果该值已被填充,则该值会阻塞,直到其他人将其清空;或者您可以从中获取一个值,如果该值已经为空,则在有人填充它之前会阻塞。它显然类似于MVar
,但对于许多常见用途,将其视为用于通信生产者/消费者对的单元素队列可能更简单。
简而言之,TVar
是通用共享状态,如果您想从任意位置对数据进行原子更新,请使用它。TMVar
是一个同步原语,如果您希望一个线程等待某些东西可用,而另一个线程等待需要的东西,请使用它。
另请注意TChan
,它大致实现为TVar
链表中的两个 s 保存位置,其中每个前向链接也是一个TVar
,并且用作通信的无界队列。
当然,所有这些都可以以稍微不同的方式使用——你可以在TMVar
不删除它的情况下查看 a 的值,例如,如果你想要一个场景,多个线程都在等待单个资源可用但它永远不会“用完了”。
和之间的差异TVar
并TMVar
没有看起来那么大——绝对不能与 和 之间的差异IORef
相提并论MVar
。
虽然MVar
确实为线程安全提供了一些锁定,TMVar
但没有什么有趣的!(没有额外的锁定)所有重要的东西都已经用STM
and实现了TVar
,所以TMVar a
它只是TVar (Maybe a)
配备一些不错的功能的简写(其中一些阻止使用该retry
功能)。
阻塞与retry
是否与精神兼容,STM
以及它是否消除了 STM 的一些优势(没有死锁等)是一个单独的问题,我希望看到更有经验的人来回答它。