[英]Haskell Concurrent.Channel: What is difference between this two codes?
为什么这个代码
import Control.Monad
import Control.Concurrent
import Control.Concurrent.STM
import Control.Concurrent.STM.TChan
main = do
ch <- newTChanIO
forkIO $ consumer ch 0
forkIO $ consumer ch 1
----------------------
forkIO $ producer ch
----------------------
return ()
producer ch = loop 0
where
loop n = do
atomically $ writeTChan ch n
threadDelay (10^5 :: Int)
loop (n+1)
consumer ch n = forever $ do
v <- atomically $ readTChan ch
print (n, v)
表现不一样
import Control.Monad
import Control.Concurrent
import Control.Concurrent.STM
import Control.Concurrent.STM.TChan
main = do
ch <- newTChanIO
forkIO $ consumer ch 0
forkIO $ consumer ch 1
----------------------
producer ch
----------------------
return ()
producer ch = loop 0
where
loop n = do
atomically $ writeTChan ch n
threadDelay (10^5 :: Int)
loop (n+1)
consumer ch n = forever $ do
v <- atomically $ readTChan ch
print (n, v)
后一个代码的输出是
(0,0)
(1,1)
(1,2)
(1,3)
(1,4)
(0,5)
(0,6)
(1,7)
...
但是,前者的输出只是
(0,0)
我打算让producer
无限期地向渠道队列ch
添加一个值,而consumer
无限期地从ch
获取一个值。
后一个代码和我的意图一样,但前一个代码没有。
在事件日志(ghc-events)中,块发生在producer
线程中的MVar上
4775372: cap 0: stopping thread 8 (blocked on an MVar)
为什么前代码(forkIO $ producer ch)不能无限期地运行。
http://hackage.haskell.org/package/base-4.10.0.0/docs/Control-Concurrent.html#g:12 :
在独立的GHC程序中,只有主线程需要终止才能使进程终止。 因此,所有其他分叉线程将简单地与主线程同时终止(这种行为的术语是“守护线程”)。
如果您希望程序在退出之前等待子线程完成,则需要自行编程。
http://chimera.labs.oreilly.com/books/1230000000929/ch07.html#sec_reminders :
[...]这告诉我们关于线程如何在Haskell中工作的重要事项: 当
main
返回时,程序终止,即使还有其他线程仍在运行 。 其他线程只是停止运行并在main
返回后停止存在。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.