Haskell:在STM事务中无限期阻塞的线程

问题描述:

有没有什么方法增加时间间隔?在此基础上,RTS决定线程在STM事务中无限期阻塞? 这里是我的代码:Haskell:在STM事务中无限期阻塞的线程

import Control.Concurrent (ThreadId) 
import Control.Concurrent.MVar (MVar,newMVar,withMVar) 
import Control.Concurrent.STM 
import qualified Control.Concurrent.ThreadManager as TM 

data ThreadManager = ThreadManager { tmCounter::TVar Int, tmTM::MVar TM.ThreadManager } 

data Settings = Settings { 
    maxThreadsCount::Int } 

createThreadManager :: Settings -> IO ThreadManager 
createThreadManager s = do 
    counter <- atomically $ newTVar (maxThreadsCount s) 
    tm <- TM.make >>= newMVar 
    return $ ThreadManager counter tm 

forkManaged :: ThreadManager -> IO() -> IO ThreadId 
forkManaged tm fn = do 
    atomically $ do 
     counter <- readTVar $ tmCounter tm 
     check $ counter > 0 
     writeTVar (tmCounter tm) (counter - 1) 
    withMVar (tmTM tm) $ \thrdmgr -> TM.fork thrdmgr $ do 
     fn 
     atomically $ do 
      counter <- readTVar $ tmCounter tm 
      writeTVar (tmCounter tm) (counter + 1) 

forkManaged确保同时运行管理线程的量不超过maxThreadsCount。它工作正常,直到重负荷。在重负载下RTS引发异常。我认为,在重负荷的情况下,在资源的硬同时竞争中,一些线程没有时间访问STM上下文。所以我认为,增加RTS决定抛出此异常的时间间隔可能会解决问题。

+4

您确定决定是否超时?我认为它使用它的日志来决定两次“重试”是否在等待。 –

+0

@丹尼尔:丹尼尔,我通过使用STM提供我的代码来更新了这个问题。这就是为什么我认为超时问题。 –

+0

是否有可能'fn'抛出一个异常,并防止计数器增加? –

Daniel Wagner是对的。这个决定不是由超时决定的。 rts中的相关代码位于Schedule.c

有关抛出异常的信息,请参见resurrectThreads函数。该评论描述了这仅仅是在GC之后被发现为垃圾的线程引发的。 ezyang描述了如何为此工作mvars:http://blog.ezyang.com/2011/07/blockedindefinitelyonmvar/

[关于当我检查其来源,并意识到,这只是一个简单的后卫/重试,而不是他在以前的文件中描述check去除坏的猜测 - 哎呀!我现在怀疑Daniel Wagner在这里也是正确的,并且问题在于某种程度上计数器没有递增。]

+0

Sclv,丹尼尔,谢谢你的回应,尤其是对于ghc的rts实施的有用链接!我会再次检查我的代码。 –