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决定抛出此异常的时间间隔可能会解决问题。
答
Daniel Wagner是对的。这个决定不是由超时决定的。 rts中的相关代码位于Schedule.c
有关抛出异常的信息,请参见resurrectThreads
函数。该评论描述了这仅仅是在GC之后被发现为垃圾的线程引发的。 ezyang描述了如何为此工作mvars:http://blog.ezyang.com/2011/07/blockedindefinitelyonmvar/
[关于当我检查其来源,并意识到,这只是一个简单的后卫/重试,而不是他在以前的文件中描述check
去除坏的猜测 - 哎呀!我现在怀疑Daniel Wagner在这里也是正确的,并且问题在于某种程度上计数器没有递增。]
+0
Sclv,丹尼尔,谢谢你的回应,尤其是对于ghc的rts实施的有用链接!我会再次检查我的代码。 –
您确定决定是否超时?我认为它使用它的日志来决定两次“重试”是否在等待。 –
@丹尼尔:丹尼尔,我通过使用STM提供我的代码来更新了这个问题。这就是为什么我认为超时问题。 –
是否有可能'fn'抛出一个异常,并防止计数器增加? –