Java並行処理プログラミングを読んだ

本の感想を書くことによりいい感じにブログネタを切らさないようにする生活(´・_・`)

だいぶ前から読んでいた本をついに読み終わりました。

www.amazon.co.jp

Scalaだとakkaとかあって、アクターモデルだ!いいかんじだ!と思ってたんですが、 やはり先人の苦労の歴史を完全にスルーできるという訳ではなさそうだし、 一度ロックとかを使った並行処理を学んでからアクターモデルを勉強したほうが、 アクターの有り難みも分かるかなと思い、非アクターな並行処理から勉強することに。

Javaの並行処理ならゲーツ本が鉄板というお墨付きをもらったのでJava並行処理プログラミングという本を選びました。

内容の紹介

マルチスレッドのデバッグは難しいというかつらいというのが身にしみました。

この本は、Badなコード(マルチスレッドだとバグるコード)がたくさん示されているのですが、 実際にこれを実装すると何回やっても正常に動作してしまって、 あれー?と思ってrunを100回くらいやると、1回だけバグるみたいなケースがたくさんありました(´;ω;`)

他にも、あるライブラリの無害なバグと別のライブラリの無害なバグが組み合わさることでデッドロックが発生するといった、 地獄のような例もあって本当につらいです。

個人的ににおもしろかった例として、p.59にあるサンプル(正しく公開されないとエラーになりそうなクラス)を挙げます。

public class Holder {
    private int n;

    public Holder(int n) { this.n = n; }
   
    public void assertSanity() {
        if (n != n) {
            throw new AssertionError("This statement is false.");
        }
    }
}

public class Checker {
    // 安全でない公開
    public Holder h;

    public void initialize() {
        holder = new Holder(42);
    }
}

なんとマルチスレッド環境で、上記のinitializeassertSanityをめちゃくちゃに叩きまくると極稀にAssertionErrorを投げる可能性がある(つまり n != nを成立させられる)らしいです。

とはいえあまりにもレア過ぎて、java - How to demonstrate race conditions around values that aren't published properly? - Stack Overflowを参考にコードを書いても再現することはできませんでした。再現するにはJavaのバージョンやハードウェアもひっくるめて頑張る必要がありそうです。がっかりなのかよかったなのか(◞‸◟)

防ぐにはCheckerでpublicにせず、synchronizedなgetter/setterを用意するとか、Holderのフィールドをfinalにして不可変にするなどがありますが、詳しくは本書を参照してみてください。

このようなマルチスレッドに関するつらさを避けるためにsynchronizedとか連打すると、今度はマルチスレッドにした意味ないよね?みたいな性能しか出なかったりして、そういう安全性とスケーラビリティの狭間で可視性とか、スレッドローカルとかを使いながらスレッドセーフなクラスを設計していく戦い方がこの本には書いてあります。

絶版なので気合で入手する必要があり、やはり並行処理はつらいという感じ(?)ですが、上記のようなつらさを味わいたい人(や仕事で味わいたくない人)は読んでみると楽しいかもしれません( ⁰⊖⁰)

内容に関する詳しいことは、既にたくさんの書評が書かれているのでそちらを参考にすると知ることが出来ると思います。

読んだ: Java 並行処理プログラミング / ブライアン・ゲーツ、ダグ・リー、他 著、岩谷宏 訳 - ひだまりソケットは壊れない

並行してakka in actionを読んだりしているので、アクターモデルがいかに辛くないか実感できています。(アクターが辛くないとは言っていない) この本の内容も読んだだけで明らかにマスターしていない感じなのですが少しずつ習得していきたいです₍₍ (ง´・_・`)ว ⁾⁾