osiire’s blog

ふしぎなそふとやさん

良いプログラマを目指すなら「Concurrent Progrmming in ML」は今すぐ読むべき

(いえ、どうせ前から広めたいとは思ってたので、ちょっと便乗。)
これからマルチコア当り前時代になるし並行処理を扱えるようになりたい。でも並行処理って難し過ぎる。そんな諸氏に朗報です。簡単かつ安全にマルチスレッドを扱える方法があります。
それは、メッセージパッシングによるスレッド間情報共有です。Erlangのようなアクターモデルと言った方がピンとくる人もいるかもしれません。メッセージパッシングの世界にはロックもシグナルも登場しません。あるのは、スレッド間で共有する通信路だけです。なぜ通信路だけで、排他制御が出来るのでしょうか?新しいスレッドを作って、そのスレッドが持つ文字列を読み書きするメッセージパッシングスタイルのプログラムを見れば一目瞭然です。

(* 細かい事は若干単純化したサンプルプログラムです。*)
let start_server init_msg =
  let ch = (* 通信路を作る *)
    new_channel ()
  in
  let rec loop msg = (* 新しく作られるスレッドのループ *)
    match receive ch with
      `Read reply -> send reply msg; loop msg
    | `Write new_msg -> loop new_msg
  in
  ignore (Thread.create loop init_msg); (* スレッド起動 *)
  ch

(* 読み込み *)
let read ch =
  let reply = new_channel () in
  send ch (`Read reply);
  receive reply

(* 書き込み *)
let write ch msg =
  send ch (`Write msg)

このプログラムは、文字列を内包するスレッドを一つ作り、通信路(ch)経由で読み込み書き込み命令がくる度に自身の文字列を返したり、更新したりしています。要するに、スレッドはループしながら単一の要求に応えるので、一切内部変数のロックをかける必要がないのです。文字列を破壊的に代入していないというのもポイントです。
(同期だとか非同期だとかいう話を横に置けば)原理はこれだけです。たったこれだけの事で、一見意味不明なmutexの扱いから解放され、マルチスレッドプログラムが劇的に簡単になります。既にErlangはそれを実証しているとも言えるでしょう。
じゃぁ、Erlangを使わなきゃいけないのかって?いえいえ、上のプログラムはOCamlのプログラムです。OCamlではメッセージパッシングの仕組みをEventモジュールと呼ばれる270行程のプログラムで実現しています。ScalaにはScala Actorがありますし、JavaにはKilim(http://www.malhar.net/sriram/kilim/)というライブラリがあります。メッセージパッシングは言語で実装しなければならないものではなく、もうライブラリとして身近にあるのです。
では、このメッセージパッシングによるマルチスレッドプログラミングを具体的にはどう書けばいいのか?その話が詳しく載っているのが「Concurrent Programming in ML」です。
http://www.amazon.com/Concurrent-Programming-ML-John-Reppy/dp/0521480892
ぜひメッセージパッシングの世界の扉を開いてみてください。