Multithreading &引用;STM事务中无限期阻塞的线程;在线程从未被阻塞的情况下
在我的程序中,我将Multithreading &引用;STM事务中无限期阻塞的线程;在线程从未被阻塞的情况下,multithreading,haskell,asynchronous,race-condition,stm,Multithreading,Haskell,Asynchronous,Race Condition,Stm,在我的程序中,我将async库与stm结合使用 主线程分叉两个线程,直到其中一个(可能是其中一个)遇到解决方案为止。该解决方案通过TMVar返回。它们都不会等待任何TMVar,除非在找到解决方案时调用putTMVar,其中一个保证永远运行,除非被杀死。那么,如果至少有一个子线程在存储结果之前不执行任何阻塞STM事务(或死亡),那么我怎么可能“在STM事务中无限期地阻塞线程”(这似乎大约每二十次发生一次) 请注意,两个子线程使用TVars相互通信,但不使用TMVars 简化代码: main ::
async
库与stm
结合使用
主线程分叉两个线程,直到其中一个(可能是其中一个)遇到解决方案为止。该解决方案通过TMVar返回。它们都不会等待任何TMVar
,除非在找到解决方案时调用putTMVar
,其中一个保证永远运行,除非被杀死。那么,如果至少有一个子线程在存储结果之前不执行任何阻塞STM事务(或死亡),那么我怎么可能“在STM事务中无限期地阻塞线程”(这似乎大约每二十次发生一次)
请注意,两个子线程使用TVar
s相互通信,但不使用TMVar
s
简化代码:
main :: IO ()
main = do
output <- newEmptyTMVar
result <- withAsync (child1 output) $ \_ -> withAsync (child2 output) $ \_ ->
let go = do
result <- atomically $ takeTMVar output
if someCondition result
then return result
else go
in go
print result
child1 :: TMVar Result -> IO ()
child1 output = go 0
where
go i = do
case computation1 i of
Nothing -> return ()
Just x -> atomically $ putTMVar x
go (i + 1)
child2 :: TMVar Result -> IO ()
-- Does some other stuff, but also only interacts with its argument to
-- give back a result, same as child1.
main::IO()
main=do
输出
放手
结果IO()
child1输出=go 0
哪里
去做
案例一
无->返回()
只需x->atomically$putTMVar x
go(i+1)
child2::TMVar结果->IO()
--做一些其他的事情,但也只与它的论点相互作用
--返回一个结果,与child1相同。
为什么您认为这是不可能的?考虑操作顺序:<代码>子1>代码>写入TMVAR,<代码>主< /代码>从TMVAR,<代码> Health1 >写入TMVAR(再次满),STM事务中的child1
和child2
块试图putTMVar
和main
此时没有对output
的实时引用。两个子线程,因此在STM事务中被阻塞。@ThomasM.DuBuisson我认为OP预期withAsync
将最终杀死(取消)这些线程,因此这里没有真正的死锁。然而,RTS没有考虑“线程终止”,并触发了一个可以说是虚假的“死锁”异常。我不是说RTS的检测策略是错误的,但在这里它处理异步。我在过去遇到过类似的问题,这确实是预期的RTS行为。相关链接:@chi有意义。即使在最好的情况下,这似乎也是一场比赛。在终止子线程或RTS确认没有输出的读取器
和为所有被阻止的子线程抛出异常之间,赢的是什么。如果在main
的分支中有超过takeTMVar
,这一点尤其现实。正确的方法是什么?