TVar和TMVar之间的区别

时间:2011-08-02 16:08:44

标签: haskell concurrency stm

我看到TVar是一个简单的容器,而TMVarMVar相同,这意味着它有一个锁等,但在{{1}内单子。我想知道为什么这是必要的,因为STM的想法是不需要锁。

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

2 个答案:

答案 0 :(得分:41)

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

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

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

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

另请注意TChan,其大致实现为链接列表中的两个TVar个持有位置,其中每个前向链接也是TVar,并且作为无限制的通信队列

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

答案 1 :(得分:19)

TVarTMVar之间的差异并不像看上去那么大 - 绝对不能与IORefMVar之间的差异相比。

虽然MVar确实为线程安全提供了一些锁定,但TMVar没有任何有趣的东西! (没有额外的锁定)所有重要内容都已经使用STMTVar实现,因此TMVar a只是TVar (Maybe a)的简写,配备了一些不错的功能(其中一些功能)阻止使用retry函数。)

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