整数値を設定または取得するために使用できる単純なスレッド セーフなクラスを作成したいと考えています。
最も簡単な方法は、synchronizedキーワードを使用することです。
public class MyIntegerHolder {
private Integer value;
synchronized public Integer getValue() {
return value;
}
synchronized public void setValue(Integer value) {
this.value = value;
}
}
volatileを使用することもできます:
public class MyIntegerHolder {
private volatile Integer value;
public Integer getValue() {
return value;
}
public void setValue(Integer value) {
this.value = value;
}
}
volatileキーワードを持つクラスはスレッドセーフですか?
次の一連のイベントを検討してください。
- スレッド A は値を 5 に設定します。
- スレッド B は値を 7 に設定します。
- スレッド C が値を読み取ります。
Java 言語仕様から、
- "1"は"3"の前に発生します
- "2"は"3"の前に発生します
しかし、「1」が「2」の前に発生するという仕様からどのように続くかわかりません。そのため、「1」は「2」の前に発生しない と思われます。
スレッド C は 7 または 5 を読み取る可能性があると思います。volatileキーワードを持つクラスはスレッドセーフではなく、次のシーケンスも可能だと思います。
- スレッド A は値を 5 に設定します。
- スレッド B は値を 7 に設定します。
- スレッド C は 7 を読み取ります。
- スレッド D は 5 を読み取ります。
- スレッド C は 7 を読み取ります。
- スレッド D は 5 を読み取ります。
- ...
MyIntegerHolder with volatileはスレッドセーフではないと仮定するのは正しいですか?
AtomicInteger を使用してスレッドセーフな整数ホルダーを作成することは可能ですか?
public class MyIntegerHolder {
private AtomicInteger atomicInteger = new AtomicInteger();
public Integer getValue() {
return atomicInteger.get();
}
public void setValue(Integer value) {
atomicInteger.set(value);
}
}
?
以下は、『Java Concurrency In Practice』の一部です。
"アトミック変数の読み取りと書き込みは、揮発性変数と同じメモリ セマンティクスを持ちます。 "
スレッドセーフなMyIntegerHolderを記述する最良の (できればノンブロッキングの) 方法は何ですか?
答えを知っているなら、それが正しいと思う理由を知りたいです。仕様通りですか?もしそうなら、どのように?