7章並行制御の基本: スレッドと MVar

並行制御の基本的な操作は、新しいスレッドを生成することです。並行Haskellにおいて、新しいスレッドを生み出すにはforkIOを使います。

forkIO :: IO () -> IO ThreadId

forkIOは引数としてIO ()型の計算を取ります。IO ()型の計算とはつまり、IOモナド内で最終的に()型の値へ評価される計算です。forkIOに渡された計算はシステム内の他のスレッドと並行に走る新しいスレッド内で実行されます。そのスレッドにエフェクトがあれば、それは他のスレッドのエフェクトと予測できない形で交錯します。

2つのスレッドを使う簡単な例で、エフェクトの交錯を説明しましょう。一方のスレッドは文字Aを繰り返し表示し、もう一方は文字Bを繰り返し表示します。

fork.hs

import Control.Concurrent
import Control.Monad
import System.IO

main = do
  hSetBuffering stdout NoBuffering            -- ①
  forkIO (replicateM_ 100000 (putChar 'A'))   -- ②
  replicateM_ 100000 (putChar 'B')            -- ③
  • ① 出力Handleをバッファリングなしのモードに設定し、エフェクトの交錯をよりはっきり見えるようにします。
  • ② スレッドを生成して文字Aを100,000回表示させます。
  • ③ メインスレッドで、文字Bを100,000回表示します。

このプログラム走らせてみると、出力は以下のようになるはずです。

AAAAAAAAABABABABABABABABABABABABABABABABABABABABABABAB ...

Get Haskellによる並列・並行プログラミング now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.