cro*_*eea 4 multithreading haskell ghc
我的代码似乎挂在readMVar另一个线程调用之后putMVar.我不指望这会发生,但这就是我所观察到的.我的主线程创建了两个新线程,每个线程都可以访问共享MVarm.
线程1:
do
putStrLn "tick"
x <- readMVar m
putStrLn "tock"
Run Code Online (Sandbox Code Playgroud)
线程2:
do
putMVar m 0
putStrLn "put m0"
void $ tryTakeMVar m
putStrLn "take m"
putMVar m 1
putStrLn "put m1"
Run Code Online (Sandbox Code Playgroud)
主要:
do
m <- newEmptyMVar
<start thread 1>
<start thread 2>
Run Code Online (Sandbox Code Playgroud)
在以下场景中,我的程序挂起:
两个线程可以访问共享的MVar m,它最初是空的.线程1阻塞readMVar m.同时,线程2调用putMVar m ....此时,线程1 可以继续,但我们假设它没有.线程2然后调用tryTakeMVar m,这可能会清空一个完整的MVar.然后线程2再次调用putMVar m ....此方案对应于以下输出:
tick
put m0
take m
put m1
<hang>
Run Code Online (Sandbox Code Playgroud)
这里发生了什么?我希望"tock"应该打印,因为线程2填满了MVar,但我的程序只是挂起.
我转向从我的无功实施base,以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
Run Code Online (Sandbox Code Playgroud)
没有真正考虑其影响.从那以后,我一直在努力做到这一点.正如丹尼尔指出的那样,旧版本base用于做类似的事情,但较新的版本具有原子tryReadMVar实现.因此即使我使用的是新版本的GHC,这个问题也会因使用而重新引入strict-concurrency.
同时,死锁发生在以下情况(Daniel描述):
putMVartryTakeMVar内部的mvartryReadMVartryTakeMVarputMVarputMVar内部时线程1死锁tryReadMVar结果证明拥有原子tryReadMVar是有用的!
| 归档时间: |
|
| 查看次数: |
70 次 |
| 最近记录: |