スピンロックとは何ですか
スピンロックといえば、マルチスレッドの下のロックメカニズムから始める必要があります。マルチプロセッサシステム環境の一部のリソースは限られているため、相互排除が必要な場合があります。この時点で、ロックメカニズムが導入されます。ロックを取得するプロセスのみがリソースアクセスを取得できます。つまり、独自の重要な領域に入るために、一度にロックを取得できるプロセスは1つだけです。同時に、2つ以上のプロセスが重要な領域に入ることはできません。クリティカルエリアを終了すると、ロックがリリースされます。
Mutexアルゴリズムを設計するとき、あなたは常にあなたがロックを持っていない状況に直面します。つまり、あなたはロックを取得しない場合はどうすればよいですか?
通常、対処する方法は2つあります。
1つは、ロックを取得していない発信者が、スピンロックのホルダーがロックをリリースしたかどうかを確認するためにそこにループしていることです。これがこの記事の焦点です - スピンロック。彼はラインシティをブロックする必要はありません(非ブロッキング)。
別の方法は、ロックを取得せずにプロセス自体(ブロッキング)し、スレッド上の他のタスクを実行し続けていることです。これは、ミューテックス(組み込みのロック同期、ReentrantLockなどを含む)です。
導入
CAS(比較とスワップ)、つまり比較と交換は、通常、スピンロックまたは楽観的ロックと呼ばれるものを実装するコア操作でもあります。
その実装は非常に簡単です。これは、期待値とメモリ値を比較することです。 2つの値が等しい場合は、メモリ値を期待値に置き換え、trueを返します。それ以外の場合は、falseを返します。
原子動作を確実にします
特定の特定の問題を解決するための技術が現れます。 CASが解決する必要がある問題は、原子動作を確保することです。原子操作とは何ですか?原子は最小で下品であり、原子操作は最小で下品な手術です。つまり、操作が開始されると、中断することはできず、操作が完了したことを知っています。マルチスレッド環境では、原子動作は糸の安全性を確保するための重要な手段です。たとえば、2つのスレッドが動作し、特定の値を変更したいとします。例として、自己増加操作を取得します。整数Iで自己輸送操作を実行するには、3つの基本的な手順が必要です。
1。iの現在の値を読み取ります。
2。I値に1を追加します。
3。I値をメモリに書き戻します。
両方のプロセスがIの現在の値を読み取るとします。この時点で、この時点でスレッドAはiに1を追加し、スレッドBは1、最終的には2ではなく1です。これは、自動挿入操作が原子動作ではなく、3つのステップに分割された3つのステップが干渉する可能性があるためです。以下の例のように、10個のスレッドの場合、各スレッドは10,000 I ++操作を実行しますが、期待値は100,000ですが、残念ながら、結果は常に100,000未満です。
静的int i = 0; public static void add(){i ++; } private static class plus runnable {@override public void run(){for(int k = 0; k <10000; k ++){add(); }}} public static void main(string [] args)throws arturtedexception {thread [] swreets = newスレッド[10]; for(int i = 0; i <10; i ++){threads [i] = new swerch(new Plus());スレッド[i] .start(); } for(int i = 0; i <10; i ++){threads [i] .jein(); } system.out.println(i); }この場合、私は何をすべきですか?そうです、おそらくあなたはすでにそれを考えていたかもしれません、あなたは同期された実装をロックまたは使用することができます、たとえば、次のADD()メソッドを変更します:
パブリック同期静的void add(){i ++; }あるいは、ロック操作は、たとえばReentrantLock(ReentrantLock)を使用して実装されます。
private static lock = new ReentrantLock(); public static void add(){lock.lock(); i ++; lock.unlock(); } CASはスピンロックを実装します
ロックまたは同期キーワードを使用してアトミック操作を実装できるため、なぜCASを使用するのですか?同期されたキーワードをロックまたは使用すると大きなパフォーマンスの損失が発生するため、CASを使用すると楽観的なロックを実現できます。実際にはCPUレベルの命令を直接利用するため、パフォーマンスは非常に高くなっています。
上記のように、CASはスピンロックを実装するための基礎です。 CASはCPU命令を使用して、操作の原子性を確保してロック効果を達成します。スピンに関しては、文字通りの意味を読むことも非常に明確です。自分で回転させると、ループです。通常、無限ループを使用して実装されます。このようにして、CAS操作は無限のループで実行されます。操作が成功し、trueを返すと、ループが終了します。 FALSEの場合、ループが実行され、CAS操作はtrueが返されるまで継続されます。
実際、JDKの多くの場所は、特にCountDownLatch、Semaphore、ReentrantLock、Java.util.concurrent.atomicパッケージなどのjava.util.concurrentパッケージでCASを使用しています。 Atomicboolean、Atomicintegerなど、誰もがAtomic*を使用していると思います。
ここでは、Atomicbooleanを例として取り上げます。
パブリッククラスAtomicbooleanはjava.io.serializable {private static final long serialversionuid = 4654671469794556979l; // unsafe.compareandswapintを使用するためのセットアッププライベート静的最終Unsafe Unsafe = unsafunsafe();プライベート静的最終的なロングバリューオフセット。 static {try {valueoffset = unsafe.objectfieldoffset(atomicboolean.class.getDeclaredfield( "value")); } catch(Exception ex){throw new error(ex); }} private volatile int value; public final boolean get(){return value!= 0; } public final boolean Compareandset(boolean expect、boolean update){int e = expect? 1:0; int u = update? 1:0; unsafe.compareandswapint(this、valueoffset、e、u)を返します。 }}これはアトミックブールのコードの一部であり、ここにはいくつかの重要な方法と特性があります。
1. sun.misc.unsafeオブジェクトが使用されます。このクラスは、メモリオブジェクトを直接操作する一連の方法を提供しますが、JDKによって内部的にのみ使用されるため、開発者が使用することはお勧めしません。
2。値は実際の値を表します。 GETメソッドは、値が0に等しいかどうかに基づいてブール値を実際に判断することがわかります。ここでの値は揮発性として定義されます。次の記事では、揮発性の可視性について説明します。
3。valueOffsetは、unsafe.objectfieldoffsetメソッドを使用して取得され、後続の比較方法として使用される値値のメモリオフセットです。
4.比較方法、これはCASを実装するコア方法です。 Atomicbooleathメソッドを使用する場合、更新する値と値を渡すだけです。 Unsafe.comPareandSwapint(this、valueOffset、e、u)メソッドが呼び出されます。これは、C ++で実装されたネイティブ方法であり、特定のコードは投稿されません。要するに、CPUのCMMPXCHG命令を使用して比較と交換を完了します。もちろん、特定のシステムバージョンによっては、実装にも違いがあります。興味のある人は、関連する記事を自分で検索できます。
シナリオを使用します
たとえば、Atomicbooleanはこのようなシナリオで使用できます。システムは、ブール変数の状態特性に基づいて、いくつかの初期化操作を実行する必要があるかどうかを判断する必要があります。それがマルチスレッド環境であり、繰り返しの実行を避ける場合、Atomicbooleanを使用して実装できます。擬似コードは次のとおりです。
プライベート最終的なstatic原子ブールフラグ= new Atomicboolean(); if(flag.compareandset(false、true)){init(); }たとえば、AtomicIntegerをカウンターやマルチスレッド環境で使用して、正確なカウントを確保することができます。
ABAの質問
CASには問題があります。これは、値がAからB、次にBからAに変化することです。この場合、CASは値が変更されていないと考えますが、実際には変更されました。この点で、バージョン番号に基づいて実装を提供する同時パケットの下にAtomicStampedReferenceがあり、いくつかの問題を解決できます。
要約します
上記は、この記事のコンテンツ全体です。この記事の内容には、すべての人の研究や仕事に特定の参照値があることを願っています。ご質問がある場合は、メッセージを残してコミュニケーションをとることができます。 wulin.comへのご支援ありがとうございます。