【问题标题】:Haskell: thread blocked indefinitely in an STM transactionHaskell:线程在 STM 事务中无限期阻塞
【发布时间】:2011-10-22 20:26:55
【问题描述】:

有没有什么办法可以增加一个时间间隔,RTS 根据这个时间间隔决定线程在 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 确保同时运行的托管线程的数量不超过 ma​​xThreadsCount。它工作正常,直到重载。在重负载下,RTS 会引发异常。我认为在重负载下,在激烈的并发资源竞争中,一些线程没有时间访问 STM 上下文。所以我认为,增加 RTS 决定抛出此异常的时间间隔可能会解决问题。

【问题讨论】:

  • 您确定该决定是通过超时做出的吗?我认为它使用日志来决定两个 retrys 何时相互等待。
  • @Daniel:丹尼尔,我已经通过使用 STM 提供我的代码更新了这个问题。这就是为什么我认为超时的问题。
  • fn 是否有可能抛出异常,并阻止计数器递增?
  • @Daniel:我是否正确,如果引发了异常,并且没有在我的代码中捕获,那么我应该在控制台中看到它吗?实际上那些 fn 在 IO 中做了一些动作,但是这些动作被包裹在 Control.Exception.catch 中,我在控制台中没有看到任何抱怨。

标签: multithreading haskell stm


【解决方案1】:

丹尼尔·瓦格纳是对的。该决定不是在超时的情况下做出的。 rts中的相关代码在Schedule.c

请参阅resurrectThreads 函数以了解引发异常的位置。注释描述了这仅被扔给在 GC 之后发现为垃圾的线程。 ezyang 描述了这对 mvar 的工作原理:http://blog.ezyang.com/2011/07/blockedindefinitelyonmvar/

[关于check 的错误猜测在我检查其来源并意识到它只是一个简单的保护/重试而不是之前的论文中描述的内容时被删除 - 哎呀!我现在怀疑 Daniel Wagner 在这里也是正确的,问题在于计数器没有增加。]

【讨论】:

  • Sclv,Daniel,感谢您的回复,特别是对 ghc 的 rts 实现的有用链接!我会再次检查我的代码。
猜你喜欢
  • 2012-05-14
  • 1970-01-01
  • 2018-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-08
  • 2015-08-01
  • 1970-01-01
相关资源
最近更新 更多