multithreading - 除非我打印一些东西,否则并发(多线程)程序会挂起
问题描述
我有一个函数,我使用forkIO将其分叉到一个线程中。该函数在ReaderT monad 转换器中运行,以便我可以传入只读配置记录:
main :: IO ()
main = do
...
forkIO $ runReaderT watcher config
该函数使用tryTakeMVar 监视watcher
MVar (我不希望它阻塞。) MVar 存储在配置中并被称为“抽屉”,因为它的行为类似于正在监视的线程之间的事务抽屉,基本上是跳过渠道。main
watcher
printThing
有一个签名printThing :: Thing -> ReaderT Config IO ()
并调用putStrLn
打印一个Thing
.
watcher :: ReaderT Config IO ()
watcher = do
cfg <- ask
mNewThing <- liftIO $ tryTakeMVar $ drawer cfg
case mNewThing of
Nothing -> do
--liftIO $ putStr "" -- uncommenting this helps
watcher
Just newThing -> do
printThing newThing
watcher
问题是程序在运行时挂起。它似乎陷入了一个循环。调用putStr ""
inmain
并没有帮助,但是,调用putStr ""
inside确实触发了线程——它开始旋转并按预期watcher
打印出s 。Thing
我能想到的只是我被懒惰咬了,但我不确定在哪里。我已经尝试过$!
尽可能使用。
我在某些条件下执行 IO 操作watcher
,但不是全部。那是问题吗?我需要在所有条件分支中执行 IO 操作吗?
ReaderT
如果有帮助,在我把所有东西都包在变压器里之前,我没有这个问题。我只是config
作为一个论点四处走动。
解决方案
尽管您的问题中有文字,但我建议您watcher
阻止。确实很少需要对 s 进行非阻塞操作MVar
;通常想要它表明你还没有完全内化“fork everything”的心态。所以:
watcher :: ReaderT Config IO ()
watcher = do
cfg <- ask
newThing <- liftIO . takeMVar $ drawer cfg
printThing newThing
watcher
我们可以单独解决“如何实现效果 X,在我看来需要非阻塞操作,而只使用阻塞操作?”形式的问题?如果您将编写一个单独的问题,其中包含有关效果 X 的一些详细信息。
旁注:我很想用以下方式写上面的内容,这具有相同的含义,但在美学上更吸引我:
watcher = forever (asks drawer >>= liftIO . takeMVar >>= printThing)
推荐阅读
- xamarin.forms - Xamarin Forms,在棱镜中设置 BarBackgroundColor NavigationPage
- javascript - 拖放和 ol.interactionSelect 上的 kml 样式
- python - 元组列表数组
- javascript - 没有 jQuery 的 HTML 表和 JavaScript addRows 和 addColumns?
- c - 如何在c中对long int进行整数除法?
- python - Python登录计数器
- ant - 未找到注释处理器“com.sun.tools.ws.processor.modeler.annotation.WebServiceAp”
- javascript - 将元素附加到数据表标题
- c++ - eclipse c++ Mac gdb调试器
- node.js - 堤坝,断路器模式,执行时抛出异常