CASとAQSを1つの記事で理解する

JAVAマルチスレッド、インタビュアーが聞きたいこと

いくつかの概念的なもの

アトミシティとは、操作が分割できないことを意味します。マルチコアかシングルコアか、原子量に関係なく、一度に1つのスレッドのみを操作できます。つまり、操作全体でスレッドスケジューラによって中断されない操作は、アトミックと見なすことができます。たとえば、a = 1;

非アトミック性:これは、スレッドスケジューラがプロセス全体で操作を中断することを意味します。
「a ++」などの操作は、次の2つの手順を実行する必要がある場合があるため、アトミックではありません。

(1)の値を取る

(2)a +1を計算する

2つのスレッドt1がある場合、t2はそのような操作を実行しています。最初のステップの後、t1は1を追加する前にスレッドスケジューラによって中断されたため、t2が実行を開始しました。t2が実行された後、t1は2番目のステップの実行を開始しました(この時点で、t1のaの値はまだ古い値です。確かではありません。スレッドt2のaの値が時間内にt1に更新されない場合にのみ表示されます)。この時点でエラーが発生し、t2の操作は無視されるのと同じです。

JAVAスレッドスケジューリング-プリエンプティブスケジューリング(優先度)


CAS-(コンペアアンドスワップ)コンペアアンドスワップ

楽観的ロック思考を採用する-常に操作を完了できると考えてください

複数のスレッドが変数を操作すると、1つのスレッドのみが正常に更新され、他のスレッドは失敗し、失敗したスレッドは再試行できます。

CASスピン待機

ロックまたはsynchronizedキーワードアトミック操作を実現できるので、なぜCASを使用するのか。ロックまたは同期されたキーワードのパフォーマンスは大きな損失をもたらしましたが、CASの楽観的ロックを実現できるため、実際にはCPUレベルの命令を直接使用するため、パフォーマンスが向上します。非常に高いです。

では、CASはどのようにしてスピンロックを実現するのでしょうか?CASはCPU命令を使用して、操作のアトミック性を確保し、ロック効果を実現します。スピンに関しては、通常、無限ループで実現されます。このように、無限ループでは、CAS操作が実行されます。操作が成功してtrueが返されると、ループは終了します。falseが返されると、ループは続行され、CAS操作はtrueが返されるまで試行され続けます。

CASソースコードを入力して確認してください
import java.util.concurrent.atomic.AtomicInteger;

update現在の値が期待値(expectと等しい場合は、値を指定された更新値()に原子的に設定しますtrueを返し、変数の値を更新します。実際の値は期待値と等しくありません。falseを返します。スレッドは何もしません。CASは現在の変数値を返します。

public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }

その中unsafe.compareAndSwapInt(this, valueOffset, expect, update);には、nativec ++実装を使用するメソッドがあり、safe.cpp JDKソースコードファイルを参照できます。CASはオペレーティングシステムで直接動作します。

public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5);

public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);

public final native boolean compareAndSwapLong(Object var1, long var2, long var4, long var6);
CASによって引き起こされるABA問題

ABAとは何ですか?

以上のことから、CASアルゴリズムの実装には重要な前提があることがわかります。つまり、メモリ内の特定の時点でデータを取り出し、次の時点で比較して置き換える必要があります。この時点での違い、データが変更された可能性があり、これがABA問題につながります。

解決策:バージョン番号(バージョン)を追加することで、その一部が解決されます。

AQSは抽象キューシンクロナイザーです

AQSは、揮発性セマンティクス(複数のスレッドでの可視性をサポート)とFIFOスレッド待機キュー(マルチスレッドの競合状態がブロックされると、このキューに入ります)を使用して共有リソース変数の状態を維持します。java.util.concurrent.locks.AbstractQueuedSynchronizerAQSと呼ばれる抽象クラス

img

AQSがリソースを共有する方法:排他的および共有

AQSは、2つのモードを提供する:排他モードと共有モードデフォルトで、およびJDKの対応する実装が有するReentrantLockReentrantReadWriteLock

排他的:実行できるスレッドは1つだけで、特定のJAVA実装にはReentrantLockがあります

共有:複数のスレッドが同時に実行されます

AQSは、volitaleとCASに基づいて実装されます。Valitaleタイプの変数状態がAQSで維持され
、リエントラントロックのリエントラント数が作成されます。この変数の周囲でロックとロック解除も実行されます。

ここに画像の説明を挿入します

推奨されるAQS分析


おすすめ

転載: blog.csdn.net/weixin_44313584/article/details/114695205