为什么putStrLn行结束是出于线程锁定?

时间:2011-07-06 16:54:55

标签: multithreading haskell io

当我在Haskell中的几个线程中使用putStrLn txt时,可以将文本插入到行尾,但是如果我使用putStr $ txt ++ "\n"总是有效。

是吗?我做错了什么?

示例1:

thread 1: putStrLn "txt 1"
thread 2: putStrLn "txt 2"
thread 3: putStrLn "txt 3"
thread 4: putStrLn "txt 4"
thread 5: putStrLn "txt 5"

输出示例:

txt 1txt 3
txt 2txt 5txt 4

示例2:

thread 1: putStr $ "txt 1" ++ "\n"
thread 2: putStr $ "txt 2" ++ "\n"
thread 3: putStr $ "txt 3" ++ "\n"
thread 4: putStr $ "txt 4" ++ "\n"
thread 5: putStr $ "txt 5" ++ "\n"

始终为线程输出一行:

txt 1
txt 3
txt 2
txt 5
txt 4

由于

更新 我正在使用ghc 6.12.3base-4.2.0.2

2 个答案:

答案 0 :(得分:7)

据我所知,Haskell没有在putStrputStrLn和朋友提供任何线程安全保证,所以它也可以逐字符交错,即使是像你一样预先连接。

有关如何正确同步I / O的示例,请参阅Can I ensure that Haskell performs atomic IO?

答案 1 :(得分:3)

使用基础4.3.0.0(putStrLn s = do putStr s; putChar '\n' - 感谢hammar)中的定义,我会假设putStr锁定stdout句柄,因此能够在不插入的情况下输出字符串。这可以解释为什么输出在使用putStrLn时会插入:锁定在putStr之后释放,而另一个线程在putChar之前获取锁定。不过,我只是在推测。

在任何情况下,更新GHC并将基础库更新为4.3.1.0应解决问题。