Vag*_*rdi 0 multithreading haskell unsafe-perform-io
以下是示例程序的来源:
当我从ghci运行它时,printJob和printJob2运行正常并将十行写入文本文件.
但是当使用-threaded标志编译时,程序只写一行.
我在ArchLinux上有ghc 7.0.3
这是编译命令:
ghc -threaded -Wall -O2 -rtsopts -with-rtsopts=-N -o testmvar testmvar.hs
Run Code Online (Sandbox Code Playgroud)
我做错了什么?为什么它不能在线程模式下工作?
import Control.Concurrent.MVar
import Control.Concurrent (forkIO)
import Control.Exception (bracket)
import Control.Monad (forM_)
import System.IO.Unsafe (unsafePerformIO)
import System.IO (hPutStrLn, stderr)
{-# NOINLINE p #-}
p :: MVar Int
p = unsafePerformIO $ newMVar (1::Int)
{-# NOINLINE printJob #-}
printJob x = bracket (takeMVar p) (putMVar p . (+ 1))
(\a -> do
appendFile "mvarlog.txt" $ "Input: " ++ x ++ "; Counter: " ++ show a ++ "\n"
)
{-# NOINLINE printJob2 #-}
printJob2 = unsafePerformIO $ do
p2 <- newEmptyMVar
return $ (\x -> bracket (putMVar p2 True) (\_ -> takeMVar p2)
(\_ -> do
appendFile "mvarlog.txt" $ "preformed " ++ x ++ "\n"
))
main = do
forM_ [1..10]
(\x -> forkIO $ printJob (show x))
Run Code Online (Sandbox Code Playgroud)
编辑:hammar指出,如果主应用程序早于所有衍生线程退出,那么它们将被杀死并建议在main结束时添加延迟.我做了,正如他预测的那样,它有效.
问题是您的主线程太快完成,并且当Haskell程序的主线程完成时,所有其他线程将自动终止.根据线程的调度方式,这可能会在任何线程有机会运行之前发生.
一个快速而肮脏的解决方案是简单地threadDelay在末尾添加一个main,但更强大的方法是使用同步原语,如MVar在主线程完成时可以发出信号.
例如:
main = do
vars <- forM [1..10] $ \x -> do
done <- newEmptyMVar -- Each thread gets an MVar to signal when it's done
forkIO $ printJob (show x) >> putMVar done ()
return done
-- Wait for all threads to finish before exiting
mapM_ takeMVar vars
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
387 次 |
| 最近记录: |