CASにおけるABA問題
3017 ワード
アーカイブCASのABAの問題.
特に注意しなければならないのは、よくあるABA問題は2種類あり、それぞれ例を挙げて説明することが要求されている.
CASの使用については、以下を参照してください.ソース|一枝の花を併発するConcurrentLinkedQueue【偽】 ソース|FutureTaskを使用した正しい姿勢 ソースコード|合併一枝花のReentrantLockとAQS(1):lock、unlock ソースコード|1本の花を併発するReentrantLockとAQS(3):Condition 1定義
1.1基本的なABA問題
CASアルゴリズムでは,メモリ内のある時点のデータ(ユーザによる)を取り出し,次の時点で比較して置き換える必要がある(CPUによる操作は原子的である).この時間差では、データの変化を招きます.
次のイベント・シーケンスを想定します.スレッド1は、メモリ位置VからAを取り出す. スレッド2は、位置VからAを取り出す. スレッド2は、Bを位置Vに書き込むためのいくつかの動作を行う. スレッド2は、Aを再び位置Vに書き込む. スレッド1はCAS動作を行い,位置Vでは依然としてAであり,動作に成功していることが分かった.
スレッド1のCAS操作は成功したが、このプロセスに問題がないわけではない.スレッド1では、スレッド2の変更が失われている.
1.2メモリモデルに関するABAの問題
ごみ回収メカニズムのないメモリモデル(C++など)では、プログラマは任意にメモリを解放できます.
次のイベント・シーケンスを想定します.スレッド1はメモリ位置VからAを取り出し、Aはメモリ位置Wを指す. スレッド2は、位置VからAを取り出す. スレッド2はいくつかの操作を行い、Aが指すメモリを解放した. スレッド2はメモリを再申請し、メモリ位置Wを適切に申請し、位置WをCの内容に格納する. スレッド2は、メモリ位置Wを位置Vに書き込む. スレッド1はCAS動作を行い、位置Vにおいて依然としてAが指すメモリ位置Wであることを発見し、動作は に成功した.
ここでは問題1.1の結果よりも深刻であり,実際の内容は既に修正されているが,スレッド1はスレッド2の修正を感知できない.
さらに、スレッド2がAが指すメモリのみを解放し、スレッド1がCASの前にAのコンテンツにアクセスする場合、スレッド1は
2例
2.1基本的なABA問題の例
位置Vにチェーンテーブルのヘッダノードが格納されている場合、ABA問題が発生したチェーンテーブルでは、元のヘッダノードがnode 1であり、スレッド2がヘッダノードを2回操作して変化している可能性があり、ヘッダノードがnode 2であることを先に修正してからnode 1(C++でも再割り当てされたノードnode 3であるが、ちょうどそのポインタが解放されたnode 1に等しい)をヘッダに挿入して新しいヘッダノードとなる可能性が高い.
スレッド1の場合、ヘッダノードは依然としてnode 1(または、C++ではアドレスが同じであるが、その内容がnode 3になる可能性があるため、ヘッダノードの値)であり、CAS操作は成功したが、ヘッダノードの後のサブチェーンテーブルの状態は予知できない.
脳補模式図.
2.2メモリモデルに関するABAの問題例
問題の定義が明らかになった.
3解決
Javaのゴミ回収メカニズムはすでに問題1.2を解決してくれた.問題1.1については、バージョン番号を追加すると解決します.
3.1 AtomicStampedReference
オブジェクト値に加えて、AtomicStampedReferenceの内部には「
AtomicStampedReferenceのいくつかのAPIは、AtomicReferenceに基づいてタイムスタンプに関する情報を追加しました.
3.2 AtomicMarkableReference
AtomicMarkableReferenceとAtomicStampedReferenceの機能は似ていますが、AtomicMarkableReferenceはより簡単な関係を説明します.その定義は、ステータススタンプを
操作時:
本文リンク:CAS中のABA問題作者:サル007出典:https://monkeysayhi.github.io本文は知識共有署名-同方式共有4.0国際許可協定の発表に基づいて、転載、演繹または商業目的に使用することを歓迎するが、本文の署名とリンクを保留しなければならない.
特に注意しなければならないのは、よくあるABA問題は2種類あり、それぞれ例を挙げて説明することが要求されている.
CASの使用については、以下を参照してください.
1.1基本的なABA問題
CASアルゴリズムでは,メモリ内のある時点のデータ(ユーザによる)を取り出し,次の時点で比較して置き換える必要がある(CPUによる操作は原子的である).この時間差では、データの変化を招きます.
次のイベント・シーケンスを想定します.
スレッド1のCAS操作は成功したが、このプロセスに問題がないわけではない.スレッド1では、スレッド2の変更が失われている.
1.2メモリモデルに関するABAの問題
ごみ回収メカニズムのないメモリモデル(C++など)では、プログラマは任意にメモリを解放できます.
次のイベント・シーケンスを想定します.
ここでは問題1.1の結果よりも深刻であり,実際の内容は既に修正されているが,スレッド1はスレッド2の修正を感知できない.
さらに、スレッド2がAが指すメモリのみを解放し、スレッド1がCASの前にAのコンテンツにアクセスする場合、スレッド1は
にアクセスする.2例
2.1基本的なABA問題の例
位置Vにチェーンテーブルのヘッダノードが格納されている場合、ABA問題が発生したチェーンテーブルでは、元のヘッダノードがnode 1であり、スレッド2がヘッダノードを2回操作して変化している可能性があり、ヘッダノードがnode 2であることを先に修正してからnode 1(C++でも再割り当てされたノードnode 3であるが、ちょうどそのポインタが解放されたnode 1に等しい)をヘッダに挿入して新しいヘッダノードとなる可能性が高い.
スレッド1の場合、ヘッダノードは依然としてnode 1(または、C++ではアドレスが同じであるが、その内容がnode 3になる可能性があるため、ヘッダノードの値)であり、CAS操作は成功したが、ヘッダノードの後のサブチェーンテーブルの状態は予知できない.
脳補模式図.
2.2メモリモデルに関するABAの問題例
問題の定義が明らかになった.
3解決
Javaのゴミ回収メカニズムはすでに問題1.2を解決してくれた.問題1.1については、バージョン番号を追加すると解決します.
3.1 AtomicStampedReference
オブジェクト値に加えて、AtomicStampedReferenceの内部には「
」が維持されています.ステータススタンプはタイムスタンプに類比でき、整数値であり、オブジェクト値を変更するたびにステータススタンプを変更し、同じオブジェクト値の異なるステータスを区別します.AtomicStampedReferenceがオブジェクト値を設定する場合、オブジェクト値およびステータススタンプは、書き込みが成功するまで所望の値を満たさなければなりません.AtomicStampedReferenceのいくつかのAPIは、AtomicReferenceに基づいてタイムスタンプに関する情報を追加しました.
// :
public boolean compareAndSet(V expectedReference, V newReference,
int expectedStamp, int newStamp)
//
public V getReference()
//
public int getStamp()
//
public void set(V newReference, int newStamp)
3.2 AtomicMarkableReference
AtomicMarkableReferenceとAtomicStampedReferenceの機能は似ていますが、AtomicMarkableReferenceはより簡単な関係を説明します.その定義は、ステータススタンプを
true|false
に簡略化することである.次のようになります.public final static AtomicMarkableReference ATOMIC_MARKABLE_REFERENCE
= new AtomicMarkableReference<>("abc" , false);
操作時:
ATOMIC_MARKABLE_REFERENCE.compareAndSet("abc", "abc2", false, true);
本文リンク:CAS中のABA問題作者:サル007出典:https://monkeysayhi.github.io本文は知識共有署名-同方式共有4.0国際許可協定の発表に基づいて、転載、演繹または商業目的に使用することを歓迎するが、本文の署名とリンクを保留しなければならない.