同時特集---ロック

4376 ワード

ReentrantLockはsynchronizedに比べて、使用できないロックを処理するための柔軟性を提供します.以下、ReentrantLockの使用について具体的にご紹介します.
1.ポーリング可能なロック要求の実現
内部ロックでは、デッドロックは致命的です.唯一のリカバリ方法はプログラムを再起動し、唯一の予防方法はプログラムを構築するときにエラーを発生させないことです.ポーリング可能なロック取得モードは、デッドロックの発生を回避するために、より完全なエラーリカバリメカニズムを有する.
必要なすべてのロックを取得できない場合は、ポーリング可能な取得方法を使用して制御権を再取得できます.これにより、すでに取得したロックが解放され、再試行されます.ポーリング可能なロック取得モードはtryLock()メソッドによって実現される.このメソッドは、呼び出し時にアイドル状態にロックされている場合にのみロックを取得します.ロックが使用可能な場合は、ロックを取得し、すぐに値trueを返します.ロックが使用できない場合、このメソッドはすぐに値falseを返します.このメソッドの一般的な使用文は次のとおりです.
    
 Lock lock = ...; 
      if (lock.tryLock()) { 
          try { 
              // manipulate protected st
          } finally { 
              lock.unlock(); 
          } 
      } else { 
          // perform alternative actions 
      } 

2.タイミング可能なロック要求の実現
内部ロックを使用すると、リクエストが開始されるとロックが停止しないため、内部ロックは時間制限のあるアクティビティの実現にリスクをもたらす.この問題を解決するために、タイミングロックを使用することができます.タイムアウトを有するアクティビティがブロックメソッドを呼び出すと、タイミングロックは、時間予算内に対応するタイムアウトを設定することができる.アクティビティが所望の時間内に結果が得られなければ,タイミングロックはプログラムを早期に戻すことができる.タイミング可能なロック取得モードは、tryLock(long,TimeUnit)メソッドによって実現される.
3.割り込み可能なロック取得要求の実現
割り込み可能なロック取得操作は、スレッドキャンセル可能なアクティビティで使用できます.lockInterruptibly()メソッドは、ロックを取得したときに応答を中断させることができます.
つまり、ReentrantLockロックはJavaイントラロックに比べて次のような特徴があります.
1)ReentrantLockはfinallyブロックでロックを解除する必要があり、synchronized同期を使用すると、JVMはロックが自動的に解放されることを保証します.
2)競合下のReentrantLock実装は,現在のsynchronized実装よりも伸縮性が高い.
3)ReentrantLockについては、複数の条件変数を関連付けることができる.
4)公平な鍵がほしいか、それとも不公平な鍵がほしいかを選択することができる.
5)ロックの高度な特性に明確な必要性がある場合、または特定の状況で同期が伸縮性のボトルネックになっていることを示す明確な証拠がない限り、synchronizedを引き続き使用する必要があります.
6)ロッククラスは普通のクラスであり,JVMはどのスレッドがロックオブジェクトを持つかを知らない.また、ほとんどの開発者はsynchronizedに精通しており、JVMのすべてのバージョンで作業することができます.
--------------------------------------------
リードライトロック
---------
リード・ライト・ロックでは、1つのリソースが複数のリード・スレッドによってアクセスされたり、1つのライト・スレッドによってアクセスされたりすることができますが、両方を同時に行うことはできません.
リード・ライト・ロックの定義を表に示します.
public interface ReadWriteLock{ 
    Lock readLock();//  
    Lock writeLock();// 。 
}
。。。。
 //    
  private final ReadWriteLock lock = new ReentrantReadWriteLock(); 
  private final Lock readLock = lock.readLock(); //    
  private final Lock writeLock = lock.writeLock(); //   
。。。。

ReadWriteLockは、読み取り専用操作と書き込み操作のペアに関連するロックを維持します.writerがない限り、読み出しロックは複数のreaderスレッドで同時に保持できます.書き込みロックは排他的です.
===========================================================================
鍵の劣勢
-----------
1.複数スレッドスケジューリングオーバーヘッド
複数のスレッドが同時にロックを要求している場合、一部のスレッドは一時停止され、後で実行が再開される可能性があります.スレッドからリカバリを開始し、本当にスケジューリングされるまで、他のスレッドがスケジューリング限度額の規定を完了するのを待つ必要がある場合があります.スレッドの停止とリカバリは、通常、大きなオーバーヘッドをもたらし、冗長な中断を伴う.ロックベースで、同期コンテナクラスなどの操作が過度に細分化されたクラスでは、ロックの競合が頻繁に発生すると、スケジューリングと実際に動作に使用されるオーバーヘッドとの比が大きくなります.
2.優先順位の逆転(priority inversion)、無限ループ、デッドロック、ロック、その他のアクティビティに失敗
------------------------------------------------------------------------
げんしへんすうるい
-----------
java.util.concurrent.atomicパッケージに原子変数クラスを追加します.すべての原子変数クラスには、プラットフォームで使用可能な最速のネイティブ構造(リンク/条件ストレージの比較および交換、ロード、最悪の場合は回転ロック)を使用して実現される「比較および設定」原語(比較および交換と同様)が公開されています.
原子変数クラスは12個あり,計量器,ドメイン更新器,配列および複合変数の4つのグループに分かれている.最も一般的な原子変数は、AtomicInteger、AtomicLong、AtomicBoolean、およびAtomicReferenceです.彼らはCASをサポートし、AtomicIntegerとAtomicLongは算術演算もサポートしています.
競合する同時アプリケーションの伸縮性を調整する一般的なテクノロジーは、使用する「ロックオブジェクトの粒度」を低減し、より多くのロック要求を競合から競合しないようにすることです.ロックから原子変数への変換は同じ結果を得ることができ,より微細な粒度の協調機構に切り替えることで競合する動作がより少なくなり,スループットが向上した.
--------------------------------------------------------------------------
ノンブロッキングアルゴリズム
------------
1つのスレッドの失敗または保留は、他のスレッドの失敗または保留に影響を与えるべきではない.このようなアルゴリズムは、非ブロックアルゴリズムと呼ばれる.
アルゴリズムの各ステップに実行を継続できるスレッドがある場合、このようなアルゴリズムをロックフリーアルゴリズムと呼ぶ.
非ブロックアルゴリズムは、デッドロックおよび優先度の逆転に「免疫性」を有する.良い非ブロックアルゴリズムは、スタック、キュー、優先キュー、ハッシュテーブルを含む多くの一般的なデータ構造に適用されている.
非ブロックアルゴリズムは、ロックベースのアルゴリズムに比べていくつかの性能優位性を有する.
まず、Java仮想マシンのロックコードパスの代わりにハードウェアのオリジナルの形態を使用し、より細かい粒度階層(独立したメモリ位置)で同期を行い、失敗したスレッドもすぐに再試行でき、保留された後に再スケジュールされることはありません.より細かい粒度は競合の機会を低減し、再スケジュールせずに再試行できる能力も競合のコストを低減します.少量の失敗したCAS操作があっても,この方法はロック競合による再スケジューリングよりもはるかに速い.
Java仮想マシンとオペレーティングシステムに深く入り込むと、非ブロックアルゴリズムはどこにでもあることがわかります.ごみ収集器は非ブロックアルゴリズムを用いて同時と平行のごみ収集を加速させる.スケジューラは,非ブロックアルゴリズムを用いてスレッドとプロセスを効率的にスケジューリングし,内在ロックを実現する.