代码之家  ›  专栏  ›  技术社区  ›  The Oddler

TVar会阻止读取直到更改吗?

  •  0
  • The Oddler  · 技术社区  · 11 月前

    我正试图弄清楚如何在Haskell中正确地在线程之间进行通信。

    我有多个线程读取一些状态,每当它发生变化时,它们都需要进行一些更新。然后我有多个线程可以改变这种状态。

    我首先看了MVar,但这行不通,因为它在写入时会阻塞,只有一个线程可以读取。

    所以我找到的最好的东西就是TVar,我可以 write 它和 read 因此,我可以让读取的线程每隔一秒左右轮询一次状态变化(微小的延迟并不重要,线程在状态之间可能会丢失也不重要)。这会奏效的。

    然而,我想知道,有没有一种方法不需要投票?我可以用其他一些原始的东西吗?或者我可以“听”TVar的一种方式?

    1 回复  |  直到 11 月前
        1
  •  2
  •   Daniel Wagner    11 月前

    只需阅读和 retry 当该值与之前相同时。

    onChanges :: Eq a => (a -> IO ()) -> TVar a -> IO b
    onChanges f tvar = readTVarIO tvar >>= go where
        go a = do
            a' <- atomically do
                a' <- readTVar tvar
                when (a == a') retry
                pure a'
            f a'
            go a'
    

    别担心,这不贵。每个 重试 将阻塞,直到 TVar 再次被写入。如果相等性检查比运行更昂贵 f ,或者如果你想跑步 f 在每次写入时,即使值没有改变,您也可以额外存储 Int 或在你的 TVar 说出它被写了多少次,并检查一下以决定是否 重试 或者不。