Java同期ロックとロック-synchronized

、synchronizedキーワード

1、同期のプロフィール

同期を達成するために、同期の基礎:各オブジェクトはロックとして使用することができますJavaの。ロックがスレッドが同期コードにアクセスしようとしたときに解放されなければならないときは、最初のオブジェクトのロック、退出を得るか、例外をスローする必要があります。

:のフォームブロック同期および同期するための方法


2、同期の利用シナリオ

  • 同期化する方法

public synchronized void method1(){}复制代码

オブジェクトがロックされているインスタンスを同期方式でオブジェクトのインスタンスは、異なるスレッドから、スレッドのみロックを取得呼び出すとき、残りが遮断されます。しかし、このクラスの異なるスレッド場合の異なるインスタンスを実行するには、オブジェクト、この同期方法を、彼らは別のロックを使用しているため、あなたはブロックされません。


  • 同期コードブロック

synchronized(this)( //ToDo}
或
synchronized(普通变量){    }复制代码

同上


  • 静的な同期方法

public synchronized static void method3(){}复制代码

このクラスは、別のスレッドがクラス呼び出したときに、ロックされている静的な同期メソッドをあなたが唯一持っている時にロックを取得するためにスレッドを1つ残りのスレッドがブロックされています


  • 静的コードブロック

synchronized(Test.class){ //ToDo}
或
synchronized(静态变量){ //ToDo}复制代码

同上


3、同期ロックのエスカレーション

ローからハイにロック状態レベルの4種類がありますが、次のとおりです。ロックフリー状態偏ったロック状態軽量ロックヘビー級のロック

ロックはアップグレードできますが、ダウングレードすることはできません、偏ったロック手段は、軽量ロックをロック偏ったにダウングレードすることはできませんアップグレードしてください。

  • バイアスされたロック

大規模な場合は、何のマルチスレッドロックを競うが、常に同じスレッド、偏ったロックによって導入コストの削減を可能にするために、スレッドで何度も取得していないだけではありません。

アクセス同期コードへの1つのスレッドがロックを取得するときに、ロックがスレッドが終了した後にヘッド及びバイアスロック格納されたスレッドIDのスタックフレーム内のオブジェクトを、記録します同期ロックを再び入る、ロックが作動し、CASする必要がありませんロック解除、単にマークのWordオブジェクトの頭部が実行バイアスロックの現在のスレッドに格納されているかどうかをテストします。

バイアスされたロック効果がある:競争の他のスレッドが存在しない場合、現在のスレッドが実行されている可能性があり、バイアス電流のスレッドでした。


  • 軽量ロック(スピンロック)

軽量ロックは、からのアップグレードによってバイアスロック。

スレッドの場合のバイアスロック動作は同期ブロックに入り、ロックが軽量バイアスロックにアップグレードするときに、第2のスレッドのロック競合に添加した場合。

  • ヘビーロック

軽量ロックの拡大した後、ロックがヘビー級にアップグレードされます。

達成するために、ヘビーモニターロックが達成したときに内部ロックオブジェクトに依存して、監視およびオペレーティング・システム依存MutexLock(ミューテックス)、また、(同期がヘビーロックである)ヘビーロックミューテックスが知られています。


バイアスされたロック

長所:なし追加のロックとロック解除の消費

デメリット:競争スレッドがあり、それは追加のロック失効消費をもたらします

シーン:シーンにシングルスレッドの同期ブロックアクセス

軽量ロック

長所:スレッドがプログラムの応答速度を改善し、競争をブロックしません。

短所:CPUを解放しないとき、スピンスレッド

シーン:応答時間を求め、シンクブロックは非常に高速に実行しました。

ヘビーロック

利点:競争がCPUを解放し、スピンスレッドを使用しません。

短所:スレッドがブロックされ、応答時間が遅いです。

シーン:特定のシンクブロックの長い実行速度の追求。


二、ロックインタフェース

1、ロックインタフェース

ロック、ロックオブジェクト。ロックする前にインタフェースは、ロック機能を達成するためにsynchronizedキーワードJavaプログラムによって、表示されます。また、新しい契約とJava SE5.0後のロックインタフェースでロック機能を実現しています。

これは、synchronizedキーワード類似の同期機能を提供していますが、両者の違いは、テキストを補完するものとして、取得し、ロックを解除するために表示する必要があり。


メインインターフェイスのメソッドをロック:

  • 空ロック()

方法を実行するときにロックがアイドル状態にあるときに、現在のスレッドがロックを取得します。ロックが別のスレッドによって保持されている場合、逆に、ロックを取得するために、現在のスレッドは禁止されています。


  • ブールのtryLock()

ロックが利用可能である場合は、ロックを取得し、すぐにそうでない場合はfalse、trueを返します。

違いのtryLock()とロック()は次のとおりです。

tryLock()は単に、ロックを取得しようとした場合、ロックが利用できない現在のスレッドが無効になってはならない、現在のスレッドがダウンコードを実行し続けています。

ロック()場合は、ロックを取得することを確認され、ロックが利用できないことは、待機ロックが得られなくなるまで、現在のスレッドが自分のダウンを続行しません。


  • 空ロック解除()

方法を行う際に、現在のスレッドは、ロックのみないスレッドがロックを保持していない場合、方法の実行が予期しない方法で生じ得る、ホルダーによって解放することができる、ロックが解除され保持されます。


  • 条件newCondition()

条件オブジェクト、通知コンポーネントを取得するために待っています。アセンブリおよび現在のロック・バインディング、ロックを取得するための唯一の現在のスレッドは、呼び出しの後に、現在のスレッドがロックを解除し、成分()メソッドを待つ呼びます。


2、ReentrantLockの使用

同期ロックを解除するために、同期ロックを取得するために、単にコールを表示するために、使用することは非常にシンプルなReentrantLockの。

ReentrantLock lock = new ReentrantLock(); //参数默认false,不公平锁
.....................

try {
    lock.lock(); //如果被其它资源锁定,会在此等待锁释放,达到暂停的效果
    //操作
}catch(Exception e){
   //异常处理
} finally {
    lock.unlock();  //释放锁
}复制代码

高同時パフォーマンスの条件の下で使用ReentrantLockのロックは、synchronizedキーワードよりもはるかに高いです。

そしてreentratnlock 公正かつ不公平ロックキューは内部的にロックされた状態に維持に基づいており、二重リンクリスト、テーブル値ノードは、それぞれが現在のスレッドのロックを要求ノードです。


3、ReadWriteLockインタフェース

次のようにメインインターフェイスをReadWriteLock:

public interface ReadWriteLock {
    /**
     * Returns the lock used for reading.
     *
     * @return the lock used for reading
     */
    Lock readLock();

    /**
     * Returns the lock used for writing.
     *
     * @return the lock used for writing
     */
    Lock writeLock();
}复制代码

ReadWriteLockロックのセットを管理、読み取り専用ロックは書き込みロックです。

Javaの並行処理ライブラリReentrantReadWriteLockは、インターフェイスを実装し、ReadWriteLockのリエントラント機能を追加しました。


ロックを読ん同時に可能にする複数のスレッドをアクセスが、書き込み処理のすべてにアクセスするためのリーダースレッド他の書き込みプロセスがされているブロックされました

ロックメンテナンス書き込み、リードロック、ライトロックをロックする一対を通して、読み書きロック分離排他ロックが大幅に向上していることが一般的同時実行と比較し、。


いくつかの機能は、読み書きロックをReentrantReadWriteLock

  • 選択的公正
  • リエントラント
  • ロックダウングレード


読み書きロック(からのプログラムの例としてblog.csdn.net/canot/artic…インターネット:):

public class Cache{
  static Map<String,Object> map = new HashMap<String,Object>();
  static ReentrantReadWriteLock  rwl = new ReentrantReadWriteLock();
  static Lock rLock = rwl.readLock();
  static Lock wLock = rwl.writeLock();

  //获取一个key对应的value
  public static final Object get(String key){
     r.lock();
     try{
         return map.get(key);
     }finally{
         r.unlock();
     }
  }

  //设置key对应的value并返回旧的value
  public static fianl Object put(String key,Object value){
     w.lock();
     try{
        return map.put(key,value);
     }final{
        w.unlock();
     }
  }

  //清空缓存
  public static fianl void clear(){
     w.lock();
     try{
        map.clear();
     } finally{
        w.unlock();
     }
  }
}复制代码


  • 読み書きロックダウングレードをロック

ロックダウングレードダウングレードは、ロックを読み取られる書き込みロックを意味しています。現在のスレッドが読み取りロックを獲得するために、再びそれを解放、その後、書き込みロックを保持している場合、プロセスは、ロック降格を呼び出すことはできません。ロックダウングレードは、読み取りロックがロック解除と呼ばれる前にロックを解除した後、書き込みのプロセスに入ると、書き込みロック再獲得を保持している時にはロックを読むことを意味します。

(から派生blog.csdn.net/qq_38737992…プログラム:

public void work() {
        reentrantReadWriteLock.readLock().lock();
 
        if (!update) {
            reentrantReadWriteLock.readLock().unlock();
 
            // 锁降级开始
            reentrantReadWriteLock.writeLock().lock();
            try {
                if (!update) {
                    // 准备数据
                    ++index;
                    try {
                        TimeUnit.MILLISECONDS.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    update = true;
                }
                reentrantReadWriteLock.readLock().lock();
            } finally {
                reentrantReadWriteLock.writeLock().unlock();
                // 锁降级结束,降级为读锁
            }
        }
        try {
            // 使用数据
            for (int i=0; i<5; i++) {
                try {
                    TimeUnit.MILLISECONDS.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + ":" + index);
            }
        } finally {
            reentrantReadWriteLock.readLock().unlock();
        }
    }
复制代码


三、同期とロックの違い

1、同期とロックの違い

インターフェイスのロックでsynchronizedキーワード、

同期状態では、ロックは、ロックを取得するかどうかを決定することができるロックを取得するか否かを判断することができません

自動的に同期ロック解除(スレッドを実行した後、同期コードを自動的にロックを解除し、ロック解除例外は、スレッドBの実行中に発生)

手動(ロック解除()メソッドがロックを解除する)ロックを解除、またはスレッドのデッドロックを引き起こす可能性が最終的にロックする必要があります。

現在のスレッドがロックを取得する場合は1、キーワードスレッド1とスレッド2を同期さつ、スレッド2待ち時間は、ブロックされたスレッド1場合、スレッド2は永遠に待ちます。

ロックロックは、必ずしも、もはや待って、あなたが終わって、スレッドが待機されていない可能性がロックしようとした場合よりも少ない得ることはありません。


ロック同期リエントラントを、不当に中断することはできません

ロックロックリエントラント、割り込みを、公平です

ロックするためのロック同期コード同期の多くは同期のためのロックコード、同期の問題の少量


非リエントラントロック:スピンロック、待って()、通知()、のnotifyAll()

再帰的に呼び出すことはできません非リエントラントロック、再帰呼び出しのデッドロックがすさまじいです


2、ReentrantLockのと同期の違い

ReentrantLockのは時間ロック中断が待って待って、複数列のロックの投票に加えて、同じ同期並行処理とメモリセマンティクスを持ちます

同期ロックを使用して、Aが解放されない、Bは永遠に待つことになります

ReentrantLockのロックを使用して、Aは、Bは、いくつかの時間割り込みレイテンシを待ち、および他の事をするだろう、解放されません。


同期JVMレベル同期ロックを監視することができるだけでなく、上に実装するが、例外コードが実行されると、監視ツールをロックの数を介してくるJVM放出。しかし、ロックではありません

資源競争が非常に激しいない状況では、同期パフォーマンスがReentrantLockのロックよりも優れている、との競争状況、同期秋の性能を数回、通常のパフォーマンスReentrantLockのを維持します。


  • 性能解析

同期されます繰り返しロックを取得するために、スピン、このプロセスで待って、中断されることはありませんスレッドので、中断オーバーヘッド節約、モーニングコンテキストスイッチ、

そしてReentrantLockのはスピンが、直接掛けません

より、この場合のように、このように、彼らはスピンロック、ロック、軽量ロックバイアスさの理由を持っているので、同期同時スレッドの少量の場合には、あってもスピンせずにバイアスされ、ロックがハングアップするスレッドを待ちません。 reenttrantlock効率的。


デフォルトでは、不当なロックを同期;デフォルト以外の公正ロックをReentrantLockの。


  • 複数の条件を結合

ReentrantLockののオブジェクトは、同時に複数の条件オブジェクトをバインドすることができ、

同期では、オブジェクトのロックwait()、及びnotify()またはnotifyAll()方法が隠された状態で実装されてもよいです。

あなたが関連して複数の時間を追加したい場合は、同期化は、余分なロックを追加する必要がありました、そしてReentrantLockのこれだけは、複数のコールする必要がありますする必要はありませんnew Condition()ことができます方法は。


おすすめ

転載: juejin.im/post/5db943fd51882564635002c2