#multithreading #haskell #stm
#многопоточность #haskell #stm
Вопрос:
Есть ли какой-либо способ увеличить интервал времени, на основе которого 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 решает выдать это исключение, может решить проблему.
Комментарии:
1. Вы уверены, что решение принято с тайм-аутами? Я думал, что он использует свои журналы, чтобы решить, когда два
retry
s ожидают друг друга.2. @Daniel: Даниэль, я обновил вопрос, предоставив свой код с использованием STM. Вот почему я думаю, что проблема с таймаутом.
3. Возможно ли, что
fn
это создает исключение и предотвращает увеличение счетчика?4. @Daniel: Я прав, если возникло исключение, которое не было обнаружено в моем коде, тогда я должен увидеть его в консоли? На самом деле эти fn выполняют некоторые действия в IO, но эти действия передаются в Control. Exception.catch , и я не вижу никаких жалоб в консоли.
Ответ №1:
Дэниел Вагнер прав. Решение не принимается с тайм-аутами. Соответствующий код в rts находится в Schedule.c
Смотрите resurrectThreads
функцию, в которой генерируется исключение. В комментарии описывается, что это выбрасывается только в потоки, признанные мусорными после GC. эзянг описал, как это работает для mvar’ов: http://blog.ezyang.com/2011/07/blockedindefinitelyonmvar /
[плохое предположение относительно check
удалено, когда я проверил его источник и понял, что это была просто простая защита / повторная попытка, а не то, что было описано в более ранней статье — упс! Теперь я подозреваю, что Дэниел Вагнер и здесь прав, и проблема в том, что счетчик не увеличивается.]
Комментарии:
1. Sclv, Даниэль, спасибо за ответ, особенно за полезные ссылки на реализацию rts ghc! Я проверю свой код еще раз.