『Java並行処理』まとめ
一通り読み終えたことだし、復習も兼ねてまとめるよ。
それにしても今の勉強スタイルはちょっと失敗かも。ちょこちょこやってちょこちょこアップするよりは、一気にまとめた方が良いかなぁ。
JMM (Java Memory Model)
近代的なコンピュータは、処理を高速化するために様々な部分に値をキャッシュしています。レジスタやメモリなど・・・CPU の多段キャッシュがあることも珍しくありません。共有メモリを使うマルチプロセッサのアーキテクチャでは、各プロセッサが自分のキャッシュを持ち、周期的にそれを主記憶に同期します。このときのキャッシュの一貫性は、プロセッサのアーキテクチャによって様々。なので、OS・コンパイラ・ランタイムはハードウェアの性質に合わせてスレッドセーフ性を確保しなければならない。そんなのやってられないよ、ということで、Java では JMM (Java Memory Model) というハードウェアのメモリを抽象化したモデルを定義し、そのモデルがどのような要件を満たさなければならないかを定義している。これにより、実際のハードウェアのアーキテクチャから比較的独立したプログラムを書くことが出来るようになっている。JVM は JMM を前提とした順序替えなどを行う。
そんなこんなで、現代の共有メモリ型マルチプロセッサにおいては、そもそも理想的なプログラムの逐次的一貫性が保たれると期待してはいけません。コンパイラは複数のスレッドがデータを共有しているとき、高速化のために様々なトリックを使い、結果としてびっくりするようなことをすることがあります。例えば、「一連の活動を構成する複数の操作の順序の見え方がスレッドごとに違う」なんてこともあります。JVM は JMM に基づいてプログラムを実行するので、プログラマは JMM を理解して適切なプログラムを組む必要があります。
例えば、JMM では「あるスレッドで書かれた変数が別のスレッドで正しく読める条件」として以下のような条件を定義しています。
- 同一スレッドで実行される場合-
- 変数による読み書きが同一のロックによるモニターを伴う場合
- 変数が volatile 宣言されている場合
丁度勉強になる記事があったので、こちらも紹介しておきます。
並行処理の基礎
何はともあれこの本で一番学んだのは、この辺りのスレッド関係の基礎知識です!スレッドセーフとは何か?どうすればスレッドセーフに出来るか。
- スレッドセーフにするには、可変なステートに対するアクセスの調停が必要
- スレッドセーフなクラスとは、必要な同期化をカプセル化しているクラス
- アトミックな複合アクション
- synchronizedブロックの意味(カウントがゼロになったらロック解放)
- volatileの意味(順序変えしなくなり、最新の値が取得出来る)
- ガード対象を明確にする
などなど。
スレッドのインタラプション
この辺りで謎だったInterruptedExceptionの意味を理解したよ!
- InterruptedExceptionの意味(待機中に割り込まれたことを通知する)
- インタラプションポリシー
- インタラプテッドステータスの保全(Thread.currentThread().interrupt())
- キャンセル処理
- デーモンスレッド(終了時に意識されない)