Why putStrLn end of line is out of thread lock?
When I use putStrLn txt
from several threads in Haskell, it's possible to get the text intercalated with the end of lines, but if I use putStr $ txt ++ "\n"
always works.
is it right? What am I doing someth开发者_Go百科ing wrong?
Example 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"
Example of output:
txt 1txt 3
txt 2txt 5txt 4
Example 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"
Always output one line for thread:
txt 1
txt 3
txt 2
txt 5
txt 4
Thanks
Update:
I'm using ghc 6.12.3
and base-4.2.0.2
As far as I can tell, Haskell doesn't provide any thread safety guarantees on putStr
, putStrLn
and friends, so it would also be allowed to interleave character-by-character, even when doing the concatenation up front like you do.
See Can I ensure that Haskell performs atomic IO? for an example of how to synchronize your I/O properly.
With the definition from base 4.3.0.0 (putStrLn s = do putStr s; putChar '\n'
- thanks hammar) I would assume that putStr
locks the stdout
handle and is therefore able to output the string without intercalation. That would explain why the output intercalates when using putStrLn
: the lock is released after putStr
and another thread acquires the lock before putChar
. I'm only speculating, though.
In any case, updating GHC and with it the base library to 4.3.1.0 should fix the problem.
精彩评论