Java言語で学ぶデザインパターン入門 マルチスレッド編
結城浩 (ソフトバンクパブリッシング)
まあまあ(10点) 2011年7月26日 ひっちぃ
日本人作者の著作の中では珍しくコンピュータ関係の技術本でベストセラーとなった前作に引き続き、今度はJava言語でのマルチスレッドを扱ったデザインパターン入門本。マルチスレッド開発において使える基本的なデザインパターンを12個解説している。
前作に対するレビューで今後メニィコアに対応したデザインパターンが求められるとか調子こいて言っていたら、前作が出た2001年の翌年にあたる2002年にとっくにこのマルチスレッドでのデザインパターンの本が出ていたことが分かり、いまさらながらこっちも読んでみた。
既に海外でこの分野の本が出ていてそれを参考にしてというかなぞって解説しているので独創性には欠けているのだろうけれど、翻訳書にありがちな読みづらさがなく、分かりやすい文章とサンプルコードで割とスラスラ読めた。
原理原則についてきっちりと踏まえているところに好感が持てた。特にImmutable「読み取りだけなら排他制御は必要ない」というまさに数学で言えばゼロにあたるデザインパターンをちゃんと説明しているほか、マルチスレッド開発における公理系とも言えるモニター(synchronized)やウェイトセットから、定理の集合とも言えるパターンランゲージにまで言及しており、コンピュータ科学にのっとった美しい解説に感心した。synchronizedを見つけたら「なにを守っているのか」に着目すると良い、のような実践的な手引きまである。
マルチスレッド自体は前世紀から注目されていて特にWindowsでは当たり前のように使われていたけれど、私はUnix系を中心に使っていて縁がなかった。そもそも当時はシングルコアが当たり前で、マルチスレッドを使う需要はほとんどなかった。マルチスレッドを扱うライブラリみたいなものはあったみたいだけど興味すら引かれなかった。必要があればマルチプロセスやノンブロッキングI/Oでやってしまえばいいと思っていた。Windowsのスレッドは扱いが面倒でトラブルが起きやすい、とかつて同僚が言っていたことがあって、じゃあノンブロッキングI/Oを使えばいいじゃんと私が言って少し喧嘩モードになったのを思い出した。
本書を読み終わってから気づいたのだけど、この本には増補改訂版が存在する。Javaは日々進化しており、実はJava 2 SE 5.0でjava.util.concurrentという便利なライブラリが追加されていて、なんとそれに合わせて200ページほど解説とサンプルコードが増えているのだそうだ。十年もしないうちに技術が古くなっていた。増補改訂版は2004年に出ている。念のためそれ以降さらにJavaが進化していないか調べてみたところ、まだ大丈夫みたいだった。そもそもマルチスレッド自体まだ枯れていないのだろう。ついでに言うとC言語ですら今も地味に進化していて、変数の定義がより柔軟にできるようになっているみたいだ。
マルチスレッドでのメモリモデルの話について少し触れられていて、とても興味深かった。スレッドにはスレッドごとのワーキングメモリがあり、スレッドがアクセスするすべてのメモリがいわばキャッシングされている。スレッド固有の変数だろうとよその変数だろうと、いったんスレッドごとのワーキングメモリにコピーされ操作されてから必要ならメインメモリに反映される。ところが同期のタイミングはモニター(synchronized)開始前後しか保証されないらしく、あとは環境依存で適当なタイミングで行われるというのだ。ほとんどの場合これでうまくいくので問題ないみたいなのだけど、Double Checked Lockingパターンのように「(あくまで排他制御の上で)モニター(synchronized)不要なのが明らかな場合はモニターせずにオブジェクトにアクセスする」場合、ちゃんとモニターしていればメモリが正常に同期されて問題ないはずが、モニターしていないことでスレッド間でのメモリの同期がおかしくなって動作が正常に行われない可能性が出てくるらしい。ちょっとこの説明では分かりにくいだろうから、気になる人は本書の付録をあたってほしい。
モニター(synchronized)以外にもvolatile修飾子でもメモリが同期されるらしい。昔少しなじみのあったC言語のvolatile修飾子と意味が少し違うので最初混乱した。Cのvolatileは一義的にはコンパイラの最適化を抑制するために存在した。昔はマルチスレッドなんて使っていなかったけれど、たとえばタイマー割り込みなんかで突発的なタイミングで書き換わる変数があったので、コンパイラの意図しないタイミングで書き換わる変数の定義にvolatileをつけないとウォーニングが出たりコンパイラが勝手に値を決め付けて動作がおかしくなった。Javaのvolatileは定義された変数のワーキングメモリとメインメモリとの同期を毎回確実に行うようにするというものだった。ついでにvolatileをつけないとlongやdoubleのような2ワード以上の変数を書き換える途中で割り込まれる可能性があるとのことで笑えた。
この本、値段を見てびっくり、なんと4,500円もする。しっかりした教科書と考えると決して高くはないのだろうけれど、今回は分野が絞られているし個々のパターンの間に重複があったり単なる組み合わせに過ぎないものもあるので、集中して読んだらすぐに読み終わってしまう。それにマルチスレッド自体、使わなくていいときは本当に使わない技術なので、手に取る人もまだ限られると思う。増補改定でなしに最初からjava.util.concurrentに対応して書かれた本を他に探した方が良いかもしれない。
(最終更新日: 2023年12月16日 by ひっちぃ)
|