阻止线程交错输出

 查建樺 发布于 2023-02-07 13:12

以下程序创建两个并发运行的线程,每个线程在打印一行文本到stdout之前随机休眠一段时间.

import Control.Concurrent
import Control.Monad
import System.Random

randomDelay t = randomRIO (0, t) >>= threadDelay

printer str = forkIO . forever $ do
  randomDelay 1000000 -- ?s
  putStrLn str

main = do
  printer "Hello"
  printer "World"
  return ()

输出通常看起来像

>> main
Hello
World
World
Hello
WoHrelld
o
World
Hello
*Interrupted
>>

你如何确保一次只有一个线程可以写入stdout?这似乎是的那种STM要善于东西,但所有STM交易必须有型STM a一些a,而且打印在屏幕上的动作有型IO a,而且似乎没有被嵌入的方式IO进入STM.

1 个回答
  • 使用STM处理输出的方法是拥有一个在所有线程之间共享的输出队列,并由单个线程处理.

    import Control.Concurrent
    import Control.Concurrent.STM
    import Control.Monad
    import System.Random
    
    randomDelay t = randomRIO (0, t) >>= threadDelay
    
    printer queue str = forkIO . forever $ do
      randomDelay 1000000 -- ?s
      atomically $ writeTChan queue str
    
    prepareOutputQueue = do
        queue <- newTChanIO
        forkIO . forever $ atomically (readTChan queue) >>= putStrLn
        return queue
    
    main = do
      queue <- prepareOutputQueue
      printer queue "Hello"
      printer queue "World"
      return ()
    

    2023-02-07 13:15 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有