10

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

4

1 回答 1

7

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

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

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

于 2011-10-25T20:10:01.180 回答