ReentrantLock(再ロック)


ReentrantLock
まずプログラムを見てみましょう.
public class DemoT {
    //            
    private static int count = 0;

    //             
    public static void inc() {
        try {
//                                。                
            Thread.sleep(1);
            count++;
//            decr();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
        }
    }


    public static void main(String[] args) throws InterruptedException {
//                   100 ,   inc        
        Thread thread = new Thread(() -> {
            for (int i = 0; i < 100; i++) {
                DemoT.inc();
            }
        });
        thread.start();
        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 100; i++) {
                DemoT.inc();
            }
        });
        thread2.start();
        Thread thread3 = new Thread(() -> {
            for (int i = 0; i < 100; i++) {
                DemoT.inc();
            }
        });
        thread3.start();
//                     
        Thread.sleep(2000);
//              
        System.out.println("count:" + count);
    }
}

希望の結果:(印刷:count:300)
実際の印刷結果:count:285(285ではないかもしれませんが、基本的には300未満)
ReentrantLock(ReentrantLock)を追加します(まだ前のコードはロックを1つ追加しただけです)
public class DemoT {
    //            
    private static int count = 0;

    //        @param fair {@code true} if this lock should use a fair ordering policy( :@param fair{@code true}             )
//        true        ,       
    static Lock lock = new ReentrantLock(true);


    //             
    public static void inc() {
        lock.lock(); //   (   )  
        try {
//                                。                
            Thread.sleep(1);
            count++;
//            decr();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();//   
        }
    }


    public static void main(String[] args) throws InterruptedException {
//                   100 ,   inc        
        Thread thread = new Thread(() -> {
            for (int i = 0; i < 100; i++) {
                DemoT.inc();
            }
        });
        thread.start();
        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 100; i++) {
                DemoT.inc();
            }
        });
        thread2.start();
        Thread thread3 = new Thread(() -> {
            for (int i = 0; i < 100; i++) {
                DemoT.inc();
            }
        });
        thread3.start();
//                     
        Thread.sleep(2000);
//              
        System.out.println("count:" + count);
    }
}

実行結果:count:300
所望の結果を実現するため、これは反発ロックであり、1つのスレッドのみが現在の範囲に入ることを許可する.
では、なぜ彼は「再入」と呼ばれているのでしょうか.現在のロックを取得できる場合、現在のロックをロックヘッドとする別のコードブロックに入ることもできるからである.たとえば、次のコード:(以前のコードか、共有変数を減算するためのメソッドボディが追加されただけです)

public class DemoT {
    //            
    private static int count = 0;

    //        @param fair {@code true} if this lock should use a fair ordering policy( :@param fair{@code true}             )
//        true        ,       
    static Lock lock = new ReentrantLock(true);


    //             
    public static void inc() {
        lock.lock(); //   (   )  
        try {
//                                。                
            Thread.sleep(1);
            count++;
            decr();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();//   
        }
    }

    public static void decr() {
        lock.lock(); //state=2   //ThreadA       :         ,          
        try {
            count--;
        } finally {
            lock.unlock(); //state=1
        }
    }

    public static void main(String[] args) throws InterruptedException {
//                   100 ,   inc        
        Thread thread = new Thread(() -> {
            for (int i = 0; i < 100; i++) {
                DemoT.inc();
            }
        });
        thread.start();
        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 100; i++) {
                DemoT.inc();
            }
        });
        thread2.start();
        Thread thread3 = new Thread(() -> {
            for (int i = 0; i < 100; i++) {
                DemoT.inc();
            }
        });
        thread3.start();
//                     
        Thread.sleep(2000);
//              
        System.out.println("count:" + count);
    }
}

予想結果:count:0
実際の実行結果:count:0
コンセプト
再読み込みはどのように実現されますか?
      volatile      ,            +1 ,        , -1;  0           
 volatile int waitStatus;

現在のロックが取得されていないスレッドはどのように操作しますか?どのように保存されていますか?
双方向チェーンテーブルで使用されます addWaiterロックされていないスレッドをキューに追加 
公平ロックと非公平ロックを区別します
非公平ロック:現在のスレッドがロックの位置に実行されている場合は、ロックを直接取得し、取得した場合はロックを直接取得し、実行します.チェーンテーブルキューで待ち続けます.
≪フェア・ロック|フェア・ロック|emdw≫:現在のスレッドがロックの場所に実行されている場合は、チェーン・テーブルに行って他のスレッドが存在するかどうかを判断し、存在する場合はキューの末尾に追加します.存在しない場合は、ロックが他のスレッドによって取得されたかどうかを判断し、存在する場合はチェーンテーブルキューに追加し、コードブロックを実行しません.