gpt4 book ai didi

multithreading - readMVar 不会在 putMVar 上唤醒

转载 作者:行者123 更新时间:2023-12-05 00:46:26 24 4
gpt4 key购买 nike

我的代码似乎卡在 readMVar 上在另一个线程调用 putMVar 之后.我不希望这种情况发生,但这就是我正在观察的。我的主线程创建了两个新线程,每个线程都可以访问共享的 MVar米。

主题 1:

do
putStrLn "tick"
x <- readMVar m
putStrLn "tock"

主题 2:
do
putMVar m 0
putStrLn "put m0"
void $ tryTakeMVar m
putStrLn "take m"
putMVar m 1
putStrLn "put m1"

主要的:
do
m <- newEmptyMVar
<start thread 1>
<start thread 2>

在以下场景中,我的程序挂起:

两个线程可以访问共享的 MVar m ,它最初是空的。线程 1 块位于 readMVar m .同时,线程 2 调用 putMVar m ... .此时,线程 1 可以继续,但我们假设它没有。然后线程 2 调用 tryTakeMVar m ,这大概会清空一个完整的 MVar .然后线程 2 再次调用 putMVar m ... .此场景对应于以下输出:
tick
put m0
take m
put m1
<hang>

这里发生了什么?我希望“tock”应该打印,因为线程 2 填充了 MVar,但我的程序只是挂起。

最佳答案

我从 base 切换了我的 MVar 实现至 strict-concurrency在尝试调试空间泄漏时。但正如问题所示,我的代码使用 tryReadMVar ,出于某种原因,strict-concurrency 未提供.因此,不久前,我实现了 tryReadMVar我自己是这样的:

tryReadMVar :: (NFData a) => MVar a -> IO (Maybe a)
tryReadMVar m = do
mm <- tryTakeMVar m
case mm of
Nothing -> return ()
Just a -> putMVar m a
return mm

没有真正考虑影响。从那以后我就忘记了做这件事。正如丹尼尔指出的,旧版本 base曾经做过类似的事情,但较新的版本有一个原子 tryReadMVar执行。因此,即使我使用的是新版本的 GHC,由于使用了 strict-concurrency,问题再次出现。 .

同时,死锁发生在以下情况(Daniel 描述):
  • 线程 1 打印“勾号”
  • 线程 2 使用 putMVar 放置 mvar
  • 线程 2 打印“put m0”
  • 线程 1 使用 tryTakeMVar 获取 mvar内tryReadMVar
  • 线程 2 使用 tryTakeMVar 获取 mvar
  • thread2 打印“take m”
  • thread2 使用 putMVar 放置 mvar
  • thread2 打印“put m1”
  • 线程 1 在尝试时发生死锁 putMVartryReadMVar

  • 原来有一个原子 tryReadMVar有用!

    关于multithreading - readMVar 不会在 putMVar 上唤醒,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54120390/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com