【问题标题】:How can I make sure main thread ends after all other threads ends?如何确保在所有其他线程结束后主线程结束?
【发布时间】:2013-05-22 18:30:31
【问题描述】:
import Control.Concurrent
main = do
    forkIO $ putStrLn "123"
    forkIO $ putStrLn "456"

上面的代码我已经写好了。但是当我执行它时,我总是只得到123456 未打印。我猜是因为主线程在另一个线程之前结束,所以整个程序刚刚结束。

如何防止这种情况发生?任何api都可以确保所有线程结束后主线程结束?

操作系统:OS X 10.8.3

编译器:ghc 7.4.2

【问题讨论】:

    标签: haskell concurrency


    【解决方案1】:

    使用async 库:

    import Control.Concurrent.Async
    
    main = do
        a1 <- async $ putStrLn "123"
        a2 <- async $ putStrLn "456"
        mapM_ wait [a1, a2]
    

    这相当于丹尼尔的解决方案,除了有两个小优点:

    • 它确保在分叉线程中引发的任何异常都会在父线程中重新引发而不会导致死锁
    • 更方便

    【讨论】:

    • 3) 来自其他语言的人很容易理解。 'async' 和 'wait' 的英文含义很容易理解。另一方面,“>> putMvar done()”和“takeMvar done”是不可理解的。
    • concurrently (putStrLn "123") (putStrLn "456")
    【解决方案2】:
    import Control.Concurrent
    main = do
        done <- newEmptyMVar
        forkIO $ putStrLn "123" >> putMVar done ()
        forkIO $ putStrLn "456" >> putMVar done ()
        takeMVar done
        takeMVar done
        -- OR: replicateM_ 2 (takeMVar done)
    

    【讨论】:

    • 但请注意异常问题。如果异常阻止子线程调用putMVar,您将在主线程中获得BlockedIndefinitelyOnMVar。您可以使用forkFinally 确保putMVar 被调用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-09
    • 2021-06-01
    • 1970-01-01
    • 2021-11-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多