2012-08-24 188 views
6
并发奇怪的行为

我有以下代码:在哈斯克尔

import Control.Concurrent 

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

这将执行上一组整数的睡眠排序,并从一个警告正常工作,除了:

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

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

+0

您是否在使用GHCi?如果是这样,它可能会以一种似乎需要并随后回响一个数字的方式表现古怪?如果不是,你的'main'是什么样的? – gspr

+0

如果您在GHCi中尝试使用此功能,请尝试输入'print'作为用户输入。 – Vitus

回答

7

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

Prelude Control.Concurrent> sleepSort [1,2,3] 
1 
Prelude Control.Concurrent> 2 
3 

您可以通过添加延迟主线程解决这个问题:

Prelude Control.Concurrent> sleepSort [1,2,3] >> threadDelay 10000 
1 
2 
3 

如果你正在运行一个编译的程序,它只是立即退出而不打印任何东西:

$ 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 
$ 

更新:而不是增加threadDelay一个电话main,您可以在sleepSort函数中使用信号量:

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] 
+0

是否有一种简单的方法来等待其他线程完成,还是增加了很多复杂性? –

+1

@BenjaminKovach查看更新。 –

+0

非常感谢! –