Haskell中并发性的奇怪行为

Ben*_*ach 6 sorting multithreading haskell sleep

我有以下代码:

import Control.Concurrent

sleepSort = mapM_ (forkIO . put)
  where put x = threadDelay (x*10000) >> print x
Run Code Online (Sandbox Code Playgroud)

这对一组整数执行睡眠排序,并且工作正常,除了一个警告:

程序按顺序打印出数据集中的每个数字,就像它应该的那样.但是,在完成打印出最后一个数字后,它会等待用户键入一些数字,然后回显该数字,然后完成.

我不认为我在任何时候都要求用户输入,为什么会发生这种情况呢?

Mik*_*kov 7

发生这种情况是因为您的主线程不等待其他线程完成.你的程序启动n个线程,但主线程立即退出,然后你返回到解释器提示符.同时其他线程继续产生输出:

Prelude Control.Concurrent> sleepSort [1,2,3]
1
Prelude Control.Concurrent> 2
3
Run Code Online (Sandbox Code Playgroud)

您可以通过向主线程添加延迟来解决此问题:

Prelude Control.Concurrent> sleepSort [1,2,3] >> threadDelay 10000
1
2
3
Run Code Online (Sandbox Code Playgroud)

如果您正在运行已编译的程序,它将立即退出而不打印任何内容:

$ cat Test.hs
import Control.Concurrent

sleepSort = mapM_ (forkIO . put)
  where put x = threadDelay (x*1000) >> print x

main = sleepSort [1,2,3]
$ ghc --make -O2 Test.hs
[1 of 1] Compiling Main             ( Test.hs, Test.o )
Linking Test ...
$ ./Test
$
Run Code Online (Sandbox Code Playgroud)

更新:您可以在函数中使用信号量,而不是添加对threadDelayto 的调用:mainsleepSort

import Control.Concurrent
import Control.Concurrent.QSemN

sleepSort l = do
  qsem <- newQSemN 0
  mapM_ (forkIO . put qsem) l
  waitQSemN qsem n
  where
    n = length l
    put qsem x = threadDelay (x*1000) >> print x >> signalQSemN qsem 1

main = sleepSort [1,2,3]
Run Code Online (Sandbox Code Playgroud)