1

AtomicInteger の有効な使用例は理解していますが、AtomicBoolean で 2 つのアクションの原子性を保証する方法について混乱しています。「ブール値の変更」およびii。AtomicBoolean変数atomicInitializedの次のよく引用されるユースケースで、initialize()などの「ワンタイムロジック」を実行します。

if (atomicInitialized.compareAndSet(false, true)) {
    initialize();
}

この操作は、最初に atomicInitialized を true に設定し (false の場合)、次に intialize() を実行しますが、これは安全ではありません。initialize() が 1 回だけ呼び出されることが保証されますが、getAndSet() にヒットする 2 番目のスレッドは、最初のスレッドが初期化を完了するまで遅延されません。そのため、ブール値の更新で原子性を提供しながら AtomicBoolean は、「if-block」全体の原子性を実際に提供するわけではなく、完全な原子性を実現するには同期/ロック メカニズムを使用する必要があります。したがって、上記のよく引用される一般的なユースケースは、実際にはアトミックではありません!!

4

1 に答える 1

7

「アトミック」クラスは、スレッドセーフなアクセスと単一変数の操作を提供することを目的としています。ifここに例として示したブロックなど、ブロック全体の同期を意図したものではありません。

java.util.concurrent.atomicパッケージの説明から:

アトミック クラスは、主にノンブロッキング データ構造と関連するインフラストラクチャ クラスを実装するためのビルディング ブロックとして設計されています。compareAndSet メソッドは、ロックの一般的な代替手段ではありません。オブジェクトの重要な更新が単一の変数に限定されている場合にのみ適用されます。

ブロック全体を同期するには、「アトミック」クラスだけに依存しないでください。他の同期コードを提供する必要があります。

于 2013-10-04T17:16:47.850 に答える