为什么这段代码
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)
我想让生产者
无限期地向 channel 队列ch
添加一个值,而消费者
无限期地从ch<中获取一个值
.
后一个代码的行为符合我的意图,但前一个代码却没有。
在事件日志 (ghc-events) 中, block 发生在 生产者
线程中的 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 :
In a standalone GHC program, only the main thread is required to terminate in order for the process to terminate. Thus all other forked threads will simply terminate at the same time as the main thread (the terminology for this kind of behaviour is "daemonic threads").
If you want the program to wait for child threads to finish before exiting, you need to program this yourself.
http://chimera.labs.oreilly.com/books/1230000000929/ch07.html#sec_reminders :
[...] This tells us something important about how threads work in Haskell: the program terminates when
main
returns, even if there are other threads still running. The other threads simply stop running and cease to exist aftermain
returns.
关于Haskell并发 channel : What is difference between this two codes?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47108943/