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