Why this code
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)
doesn't behave the same way as
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)
The latter code's output is
(0,0)
(1,1)
(1,2)
(1,3)
(1,4)
(0,5)
(0,6)
(1,7)
...
But, the former one's output is only
(0,0)
I intended that producer indefinitely add a value to the channel queue ch, and consumer indefinitely take a value from ch.
The latter code acts as well as my intension, but the former one doesn't.
In the eventlog (ghc-events), block happens on an MVar in producer thread
4775372: cap 0: stopping thread 8 (blocked on an MVar)
Why the former code (forkIO $ producer ch) doesn't indefinitely run.
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
mainreturns, even if there are other threads still running. The other threads simply stop running and cease to exist aftermainreturns.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With