以下程序创建两个并发运行的线程,每个线程在打印一行文本到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 ()