我创建了这个小程序,它创建了一个长时间运行的 thunk,最终由于异常而失败。然后,多个线程尝试评估它。
import Control.Monad
import Control.Concurrent
import Control.Concurrent.MVar
main = do
let thunk = let p = product [1..10^4]
in if p `mod` 2 == 0 then error "exception"
else ()
children <- replicateM 2000 (myForkIO (print thunk))
mapM_ takeMVar children
-- | Spawn a thread and return a MVar which can be used to wait for it.
myForkIO :: IO () -> IO (MVar ())
myForkIO io = do
mvar <- newEmptyMVar
forkFinally io (\_ -> putMVar mvar ())
return mvar
增加线程数显然对计算没有影响,这表明失败的 thunk 会保留异常作为结果。这是真的吗?这种行为是否在某处记录/指定?
更新:forkFinally
将行更改为
forkFinally io (\e -> print e >> putMVar mvar ())
确认每个线程都因异常而失败。