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 something 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With