【发布时间】:2019-01-10 00:24:08
【问题描述】:
在另一个线程调用putMVar 之后,我的代码似乎挂在readMVar 上。我不希望会发生这种情况,但这就是我所观察到的。我的主线程创建了两个新线程,每个线程都可以访问共享的MVar m。
线程 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,它最初是空的。 readMVar m 上的线程 1 块。同时,线程 2 调用putMVar m ...。此时,线程 1 可以 继续,但我们假设它没有。线程 2 然后调用tryTakeMVar m,这可能会清空一个完整的MVar。然后线程 2 再次调用putMVar m ...。此场景对应于以下输出:
tick
put m0
take m
put m1
<hang>
这里发生了什么?我希望打印“tock”,因为线程 2 填充了 MVar,但我的程序只是挂起。
【问题讨论】:
-
什么版本的 GHC?在旧版本中,
readMVar是takeMVar后跟putMVar(不是原子执行的)。如果tryTakeMVar和第二个putMVar发生在它们之间,它将解释您所看到的行为。 -
我相信 GHC 8.6.3,虽然在使用 Stack 时有点难以分辨。但是,鉴于您的清晰解释,我将尝试更深入地了解正在使用的版本。
-
确认是 GHC 8.6.3。
-
问题是:我使用的是严格并发,它不提供
tryReadMVar。结果,我自己使用tryTakeMVar和putMVar(非原子)实现了它。因此,丹尼尔所说的是正确的。 -
你应该把它写下来作为答案。追踪它是件好事。
标签: multithreading haskell ghc