iJavaのAtomic変数についての解説をMarkdown形式でまとめました。
このままファイル(例:java_atomic.md)として保存し、VS Codeのプレビュー機能や pandoc などを使ってPDFに変換してご活用ください。
Java Atomic変数 解説資料¶
1. Atomic変数とは?¶
Javaの java.util.concurrent.atomic パッケージに含まれるクラス群です。
マルチスレッド環境において、**ロック(synchronized)を使わずに、変数への操作を「不可分(Atomic)」に行う**ために使用されます。
なぜ必要なのか?¶
通常の int 型に対する count++ は、内部で「読み込み」「加算」「書き込み」の3つのステップに分かれています。複数のスレッドが同時にこれを行うと、計算結果が上書きされて消えてしまう**データ競合(Race Condition)**が発生します。
2. 核心技術:CAS (Compare-And-Swap)¶
Atomicクラスは、CPUレベルの命令である CAS を利用してスレッドセーフを実現しています。
- 比較: 現在の変数の値が、自分の知っている値(期待値)と同じか確認する。
- 置換: 同じであれば、新しい値に書き換える。
- リトライ: もし他者が先に書き換えていて値が違っていたら、失敗として値を読み直してやり直す。
この仕組みにより、スレッドを停止(ブロック)させることなく安全な更新が可能です。
3. 主要なクラスとメソッド¶
| クラス | 説明 |
|---|---|
AtomicInteger |
int型の値を操作 |
AtomicBoolean |
boolean型の値を操作 |
AtomicReference<V> |
オブジェクトの参照を操作 |
よく使われるメソッド (AtomicIntegerの例)¶
get(): 現在の値を返す。set(int newValue): 値を更新する。incrementAndGet(): 1増やした後の値を返す (++i)。getAndIncrement(): 増やす前の値を返す (i++)。compareAndSet(int expect, int update): 値がexpectならupdateに更新し、成否をbooleanで返す。
4. 演習問題¶
以下の知識を確認するための問題です。
第1問:基本概念¶
マルチスレッド環境において、以下のコードを10個のスレッドで同時に1000回ずつ実行しました。実行後の count の値が必ずしも 10000 にならない理由を説明してください。
第2問:メソッドの選択¶
AtomicInteger を使って、「現在の値が 10 の場合のみ、値を 20 に更新する」 という処理を実装したい場合、どのメソッドを使用するのが適切ですか?また、そのメソッドの戻り値は何を表しますか?
第3問:実行結果の予測¶
以下のプログラムを実行した際、コンソールに出力される値は何ですか?
AtomicInteger atomic = new AtomicInteger(5);
int result = atomic.addAndGet(10);
System.out.println(result);
System.out.println(atomic.get());
5. 解答¶
第1問¶
count++ 操作が 原子(Atomic)的ではないから です。
「値の読み込み」「加算」「書き込み」の間に他のスレッドが割り込んで古い値を読み込んでしまうため、更新の衝突(ロストアップデート)が発生します。
第2問¶
- メソッド:
compareAndSet(10, 20) - 戻り値: 更新に成功した場合は
true、現在の値が期待値(10)と異なり更新できなかった場合はfalseを返します。
第3問¶
- 1つ目の出力:
15(addAndGetは加算後の値を返すため) - 2つ目の出力:
15(変数自体の値も更新されているため)
このMarkdownをPDF化するお手伝いや、さらに詳細なコード例が必要であれば教えてくださいね。ビルドしたEmacsでこのMarkdownを編集するのも良い練習になるかもしれません!