1。CASおよび同期の適用可能なシナリオ
1.リソース競合が少ない状況では、スレッドブロッキングとウェイクアップスイッチングおよびユーザー状態カーネル間のスイッチング操作に同期した同期ロックを使用して、CPUリソースの無駄です。 CASはハードウェアに基づいて実装されていますが、カーネルに入る必要はなく、スレッドを切り替える必要はなく、操作スピンの可能性が少ないため、より高いパフォーマンスを取得できます。
2。深刻なリソース競争の場合、CASスピンの確率は比較的高く、したがって、より多くのCPUリソースを無駄にし、同期するよりも効率が低くなります。 java.util.concurrent.atomicパッケージのAtomicIntegerクラスを例にとると、そのgetandincrement()メソッドは次のように実装されています。
public final int getandincrement(){for(;;){int current = get(); int next = current + 1; if(compareandset(current、next))return current; }}比較(現在、次の)メソッドが正常に実行されると、直接返されます。スレッド競争が激しい場合、CPUによって割り当てられたスライスが排出されるまでループされて待機し、それにより効率が大幅に低下するまで、スレッド競合が激しい場合、ループがループされ、待機されます。
2。CASエラーの使用シナリオ
パブリッククラスcasdemo {private final int thread_num = 1000;プライベートファイナルint max_value = 20000000; Private AtomicInteger Casi = new AtomicInteger(0); private int synci = 0; private string path = "/users/ping/dataCenter/books/linux/linux common commants.txt"; public void casadd()throws arturnedexception {long begin = system.currenttimemillis(); thread [] threads = new Thread [thread_num]; for(int i = 0; i <thread_num; i ++){threads [i] = new runnable(){public void run(){while(casi.get()<max_value){casi.getandincrement();}}});スレッド[i] .start(); } for(int j = 0; j <thread_num; j ++){threads [j] .jein(); } system.out.println( "CASコスト時間:" +(system.currenttimemillis() - begin)); } public void syncadd()throws arturnedexception {long begin = system.currenttimemillis(); thread [] threads = new Thread [thread_num]; for(int i = 0; i <thread_num; i ++){threads [i] = new runnable(){public void run(){synci <max_value){synchronized( "synci"){++ synci;}}}}});スレッド[i] .start(); } for(int j = 0; j <thread_num; j ++)threads [j] .jein(); system.out.println( "同期費用時間:" +(system.currenttimemillis() - begin)); }}私のデュアルコアCPUで実行されると、結果は次のとおりです。
異なるスレッドの下では、CASの計算を使用して費やす時間は同期の時間よりもはるかに多いことがわかります。その理由は15行目です
14(casi.get()<max_value){15 casi.getandincrement(); 16}操作は非常に時間のかかる操作です。 15行が実行された後、ループがすぐに入力され、実行が継続され、その結果、深刻なスレッドの競合が発生します。
3. CAS使用シナリオの改善
上記の問題を解決するためには、各ループの実行時間を長くする必要があります。つまり、スレッドの競合を大幅に減らすことができます。次のようにコードを変更します。
パブリッククラスcasdemo {private final int thread_num = 1000;プライベートファイナルint max_value = 1000; Private AtomicInteger Casi = new AtomicInteger(0); private int synci = 0; private string path = "/users/ping/dataCenter/books/linux/linux commonコマンド詳細説明"; public void casadd2()throws arturnedexception {long begin = system.currenttimemillis(); thread [] threads = new Thread [thread_num]; for(int i = 0; i <thread_num; i ++){threads [i] = new runnable(){public void run(){while(casi.get()<max_value){casi.getandincrement(); try(inputstream in = new fileinputstream(new file(new file(new file(path)){catt() e){e.printstacktrace();スレッド[i] .start(); } for(int j = 0; j <thread_num; j ++)threads [j] .jein(); System.out.println( "casランダムコスト時間:" +(system.currenttimemillis() - begin)); } public void syncadd2()throws arturnedexception {long begin = system.currenttimemillis(); thread [] threads = new Thread [thread_num]; for(int i = 0; i <thread_num; i ++){threads [i] = new runnable(){public void run(){while(synci <max_value){synchronized( "synci"){++ synci;} try(inputstream in = new fileInputStream in =! catch(ioexception e){e.printstacktrace()}}});スレッド[i] .start(); } for(int j = 0; j <thread_num; j ++)threads [j] .jein(); system.out.println( "同期費用時間:" +(system.currenttimemillis() - begin)); }}whileループでは、ファイルの内容を読み取る操作が追加され、約40msかかり、スレッドの競合が減少します。テスト結果は次のとおりです。
リソースの競合が比較的小さい場合、CASメソッドと同期化された同期効率が類似していることがわかります。 CASが同期するよりも高いパフォーマンスを達成できないのはなぜですか?
テストで使用されるJDKは1.7です。 JDK1.6から始めて、ロックコアリング、ロックエリミネーション、軽量ロック、バイアスロック、適応型回転、その他の技術など、ロック操作を減らすなど、ロックの実装に多くの最適化が導入されています。スピンロックの原理はCASスピンに似ており、CASスピンよりもさらに最適化されています。詳細については、1回目の詳細なJVMロックメカニズムを参照してください。
4。概要
1. CASを使用する場合、スレッドの競合が深刻な場合、プログラムのパフォーマンスは大幅に低下します。 CASは、スレッドの競合が少ない状況にのみ適しています。
2。JDK1.6以降、同期が改善され、最適化されました。同期の基礎となる実装は、主にロックフリーのキューに依存しています。基本的なアイデアは、スピンをブロックし、競争の切り替え後もロックを競い合い続け、公平性をわずかに犠牲にしますが、高いスループットを獲得することです。スレッドの競合が少ない場合、同様のパフォーマンスを取得できます。深刻なスレッドの競合がある場合、パフォーマンスはCASのパフォーマンスよりもはるかに高くなります。
Java Concurrentプログラミングの上記の概要 - CASを慎重に使用することは、編集者の詳細な説明です。私はそれがあなたに参照を与えることができることを願っています、そしてあなたがwulin.comをもっとサポートできることを願っています。