Warm tip: This article is reproduced from serverfault.com, please click

multithreading-阻止线程交错输出

(multithreading - Stop threads from interleaving output)

发布于 2013-12-31 09:06:01

下面的程序创建两个并发运行的线程,每个线程休眠一段随机的时间,然后在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,并且似乎没有成为一个方式嵌入IOSTM

Questioner
Chris Taylor
Viewed
11
shang 2013-12-31 18:50:14

使用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 ()