Haskell并发 channel : What is difference between this two codes?

标签 haskell concurrency channel

为什么这段代码

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 after main returns.

关于Haskell并发 channel : What is difference between this two codes?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47108943/

相关文章:

haskell - 在 Haskell 中从字符串中删除字符

haskell - 是否可以以不同的方式编写与 "textbook"一样快的阶乘函数?

Haskell计算函数执行时间

scala - 带有 var 的不可变映射或带有 val 的可变映射?

c# - 合并暂时关闭的事件时提高效率和公平性

struct - 有没有办法强制转换结构以通过 channel 发送

go - 停止阻塞的 goroutine

linux - 如果 stderr 和 stdout 被重定向,进程会挂起

multithreading - 具有高并发执行的 Golang http.Client 中的 panic

Go 的 sync.WaitGroup 丢失了其中一个响应