【问题标题】:Why putStrLn end of line is out of thread lock?为什么 putStrLn 行尾没有线程锁?
【发布时间】:2011-09-29 19:38:11
【问题描述】:

当我在 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

【问题讨论】:

  • 我无法重现您在 GHC 7.0.3 上描述的行为 - 我正在使用 forkIO 并尝试了线程和非线程运行时。另外,看看hackage.haskell.org/packages/archive/base/latest/doc/html/src/… 的 GHC 实现,这两种情况的处理方式似乎没有真正的区别。
  • @Antti:似乎在base 4.3.1.0 中已更改。在base 4.3.0.0 和更早的it's defined as putStrLn s = do putStr s; putChar '\n'

标签: multithreading haskell io


【解决方案1】:

据我所知,Haskell 没有为putStrputStrLn 和朋友提供任何线程安全保证,因此它也允许逐个字符交错,即使在进行串联时也是如此像你一样在前面。

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

【讨论】:

  • 谢谢,我一直以为锁是用在putStrLn里面的。
【解决方案2】:

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

无论如何,将 GHC 及其基础库更新到 4.3.1.0 应该可以解决问题。

【讨论】:

    猜你喜欢
    • 2020-07-17
    • 1970-01-01
    • 2012-10-29
    • 1970-01-01
    • 1970-01-01
    • 2018-10-19
    • 2019-11-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多