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);
には、native
c ++実装を使用するメソッドがあり、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.AbstractQueuedSynchronizer
AQSと呼ばれる抽象クラス
AQSがリソースを共有する方法:排他的および共有
AQSは、2つのモードを提供する:排他モードと共有モードデフォルトで、およびJDKの対応する実装が有する
ReentrantLock
とReentrantReadWriteLock
排他的:実行できるスレッドは1つだけで、特定のJAVA実装にはReentrantLockがあります
共有:複数のスレッドが同時に実行されます
AQSは、volitaleとCASに基づいて実装されます。Valitaleタイプの変数状態がAQSで維持され
、リエントラントロックのリエントラント数が作成されます。この変数の周囲でロックとロック解除も実行されます。