繁体   English   中英

Haskell Concurrent.Channel:这两个代码有什么区别?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM