当我在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.3
和base-4.2.0.2
答案 0 :(得分:7)
据我所知,Haskell没有在putStr
,putStrLn
和朋友提供任何线程安全保证,所以它也可以逐字符交错,即使是像你一样预先连接。
有关如何正确同步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应解决问题。