回答:
複数のスレッドがブール値を確認および変更する必要がある場合。例えば:
if (!initialized) {
initialize();
initialized = true;
}
これはスレッドセーフではありません。あなたはそれを修正することができますAtomicBoolean
:
if (atomicInitialized.compareAndSet(false, true)) {
initialize();
}
true
ときに見ることができますinitialize()
。したがって、他のスレッドがの完了を気にしない場合にのみ機能しinitialize()
ます。
initialized
1つだけのスレッドがinitialize()
メソッドを呼び出すことを保証するためだけに使用されている場合、これは完全に有効な実際の例だと思います。明らかにinitialized
真であることは、初期化は間違いなく、この場合には完了したので、ということではないかもしれないわずかに異なる用語が良いここになります。繰り返しますが、それはそれが何に使用されているかに依存します。
volatile boolean
と同じではありませAtomicBoolean
ん。
synchronized
ブロックを使用することです。この場合、は不要になりAtomicBoolean
、だけになりvolatile boolean
ます。(if(! this.initialized) { synchronized(this) { if(! this.initialized) { initialize(); this.initialized = true; } } }
とマークinitialize
されている場合、1つのスレッドのみがを呼び出し、他のすべてのスレッドが呼び出しを待機します。)initialized
volatile
こちらが私が作成したメモ(ブライアンゲッツの本から)です。
AtomicXXXクラス
非ブロッキングの比較とスワップの実装を提供する
ハードウェアが提供するサポート(IntelのCMPXCHG命令)を利用します。これらのアトミック同時実行APIを使用するコードで多数のスレッドが実行されている場合、オブジェクトレベルのモニター/同期を使用するコードよりもはるかに優れたスケーリングが可能です。Javaの同期メカニズムはコードを待機させるため、クリティカルセクションを通過するスレッドが多数ある場合、同期メカニズム自体の管理(待機、通知など)にかなりのCPU時間を費やします。新しいAPIはハードウェアレベルのコンストラクト(原子変数)と待機およびロックフリーアルゴリズムを使用してスレッドセーフを実装するため、同期の管理よりも「処理」に多くのCPU時間が費やされます。
スループットが向上するだけでなく、デッドロックや優先順位の逆転などの活性の問題に対する耐性も向上します。
アトミックブールを使用できる主な理由は2つあります。まず変更可能です。たとえば、それを参照として渡し、ブール値自体に関連付けられている値を変更できます。
public final class MyThreadSafeClass{
private AtomicBoolean myBoolean = new AtomicBoolean(false);
private SomeThreadSafeObject someObject = new SomeThreadSafeObject();
public boolean doSomething(){
someObject.doSomeWork(myBoolean);
return myBoolean.get(); //will return true
}
}
そしてsomeObjectクラスで
public final class SomeThreadSafeObject{
public void doSomeWork(AtomicBoolean b){
b.set(true);
}
}
さらに重要なのは、そのスレッドセーフであり、クラスを保守している開発者に、この変数が変更されて複数のスレッドから読み取られることが予想されることを示すことができます。AtomicBooleanを使用しない場合は、使用しているブール変数を揮発性として宣言するか、フィールドの読み取りと書き込みの前後で同期して、ブール変数を同期する必要があります。
AtomicBoolean
クラスはあなたがアトミックに更新できるというブール値を与えます。ブール変数にアクセスする複数のスレッドがある場合に使用します。
java.util.concurrent.atomicパッケージの概要はあなたにこのパッケージのクラスは何をすべきかの良いハイレベルの記述を与え、ときにそれらを使用します。また、Brian Goetz 著のJava Concurrency in Practiceもお勧めします。
パッケージの説明からの抜粋
パッケージjava.util.concurrent.atomic description:単一の変数でロックフリーのスレッドセーフなプログラミングをサポートするクラスの小さなツールキット。[...]
これらのメソッドの仕様により、最新のプロセッサで利用できる効率的なマシンレベルのアトミック命令を実装で使用できるようになります。[...]
クラスAtomicBoolean、AtomicInteger、AtomicLong、およびAtomicReferenceのインスタンスはそれぞれ、対応する型の単一の変数へのアクセスと更新を提供します。[...]
アトミックのアクセスと更新のメモリ効果は、一般に揮発性物質の規則に従います。
- getには、揮発性変数を読み取るメモリ効果があります。
- setには、揮発性変数の書き込み(割り当て)によるメモリー効果があります。
- weakCompareAndSetは、変数をアトミックに読み取り、条件付きで書き込み、その変数に対する他のメモリ操作に関して順序付けられますが、それ以外は通常の不揮発性メモリ操作として機能します。
- compareAndSetおよびgetAndIncrementなどの他のすべての読み取りおよび更新操作には、揮発性変数の読み取りと書き込みの両方のメモリ効果があります。
volatile boolean
VSAtomicBoolean
:stackoverflow.com/questions/3786825/...