下面的程序创建两个并发运行的线程,每个线程休眠一段随机的时间,然后在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
。
使用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 ()