Javaデッドロックコードのデモ(史上最も一般的な理解)


Javaデッドロックコードのデモ
デッドロックの概念
知識の蓄積
オブジェクトロック:Javaはすべてオブジェクトで、各クラスにはclassファイルがあります.classファイルからオブジェクトをnewできます.javaオブジェクトを簡単に認識します.オブジェクトにはオブジェクトヘッダ情報、つまりこのオブジェクトの概要があります.1つの情報はオブジェクトロックです.つまり、現在のオブジェクトがロックされているかどうか、どの参照によってロックされているかです.
synchronized:synchronizedはjavaキーワードで、もし方法に適用して私たちがロックしているのがこの方法であれば、私たちがロックしているコードブロックは、このコードブロック内で私たちがこのロックを持っていることを表し、Java Effectiveもロックの範囲を減らすことを提唱しています.同期コードブロックに入るとロックされ、同期コードブロックを実行するとロックが解放されます.
デッドロック:一般的には死んだロックと理解されています.死んだロックがなければ、その宣言周期は、ロックを持つ->ロックを解放することです.死後、ロックを保持しているがロックを解放しないと理解できます.つまり、同期コードブロックが実行されていませんか?同期コードブロックのどこが実行されていないかを分析するだけでいいので、次の例を見てみましょう.
デッドロックの表示
package com.yang.kuangTeacher;

import java.util.concurrent.TimeUnit;

/**
 * @author: fudy
 * @date: 2020/9/13    12:21
 * @Decription:     (    B    JAVA)
 **/
public class DeadLock {
     

    public static void main(String[] args) {
     
        MarkUp markUp0 = new MarkUp("    ",0);
        MarkUp markUp1 = new MarkUp("  ",1);
        markUp0.start();
        markUp1.start();
    }
}

//    
class LipStick {
     
}

//    
class Mirror {
     
}

//    
class MarkUp extends Thread {
     

    private int choice;
    private String userName;

    private static LipStick lipStick = new LipStick();
    private static Mirror mirror = new Mirror();

    MarkUp(String userName, int choice) {
     
        this.userName = userName;
        this.choice = choice;
    }

    @Override
    public void run() {
     
        try {
     
            markUP();
        } catch (InterruptedException e) {
     
            e.printStackTrace();
        }
    }

    private void markUP() throws InterruptedException {
     
        //     0    
        if (choice == 0) {
     
            //        ,        
            synchronized (lipStick) {
     
                System.out.println(userName + "     ");
                //          
                TimeUnit.SECONDS.sleep(1);
                //           		 -----------------    ----------------------->
                synchronized (mirror) {
     
                    System.out.println(userName + "     ");
                }
            }
        }
        //     1    
        if (choice == 1) {
     
            //        ,        
            synchronized (mirror) {
     
                System.out.println(userName + "     ");
                //          
                TimeUnit.SECONDS.sleep(1);
                //                    -----------------    ----------------------->
                synchronized (lipStick) {
     
                    System.out.println(userName + "     ");
                }
            }
        }
    }
}


デッドロックは、同期コードブロックが実行されていないため、ロックが解放されないと考えられていましたが、上記の2つのデッドロックの原因を分析しました.
  • スレッド1方式0メイクで口紅ロックを手に入れた後、1秒間睡眠(スレッド2を先に実行する可能性がある)
  • スレッド2方式1メイクでミラーロックを手に入れたので、1秒
  • 睡眠
    スレッド1が先に口紅ロックを取得して実行が完了すると、鏡ロックを持つ準備をしていると、鏡オブジェクトが保持されていることに気づき、鏡ロックが解放されるのを待つ.
    スレッド2はまずミラーロックを取得し、口紅ロックを取ろうとすると、口紅オブジェクトが保持されていることに気づき、口紅ロックが解放されるのを待つ.
    プログラムを閉じなければ、2つのスレッドはずっと待っています.デッドロックと理解でき、ロックを解放できません.
    デッドロックの解決
    上記の例では、2つのロックを同時に手に入れて1つのことをしようとするとデッドロックになるので、Java Effectiveがロックの範囲を減らすことを提唱しているように、問題を改善しています.
    私たちは口紅ロックを手に入れた後、口紅方法を実行した後、口紅ロックを解放することができます.鏡ロックをしたいなら、コードブロックを同期して鏡ロックを持ってください.
    package com.yang.kuangTeacher;
    
    import java.util.concurrent.TimeUnit;
    
    /**
     * @author: fudy
     * @date: 2020/9/13    12:21
     * @Decription:     (    B    JAVA)
     **/
    public class DeadLock {
         
    
        public static void main(String[] args) {
         
            MarkUp markUp0 = new MarkUp("    ",0);
            MarkUp markUp1 = new MarkUp("  ",1);
            markUp0.start();
            markUp1.start();
        }
    }
    
    //    
    class LipStick {
         
    }
    
    //    
    class Mirror {
         
    }
    
    //    
    class MarkUp extends Thread {
         
    
        private int choice;
        private String userName;
    
        private static LipStick lipStick = new LipStick();
        private static Mirror mirror = new Mirror();
    
        MarkUp(String userName, int choice) {
         
            this.userName = userName;
            this.choice = choice;
        }
    
        @Override
        public void run() {
         
            try {
         
                markUP();
            } catch (InterruptedException e) {
         
                e.printStackTrace();
            }
        }
    
        private void markUP() throws InterruptedException {
         
            //     0    
            if (choice == 0) {
         
                //        ,        
                synchronized (lipStick) {
         
                    System.out.println(userName + "     ");
                    TimeUnit.SECONDS.sleep(1);
                }
                //                     ------------------------  ---------------------------
                synchronized (mirror) {
         
                    System.out.println(userName + "     ");
                }
            }
            //     1    
            if (choice == 1) {
         
                //        ,        
                synchronized (mirror) {
         
                    System.out.println(userName + "     ");
                    TimeUnit.SECONDS.sleep(1);
                }
                //                      ------------------------  ---------------------------
                synchronized (lipStick) {
         
                    System.out.println(userName + "     ");
                }
            }
        }
    }
    
    

    ロックをタイムリーに解放することによって、つまり同期コードブロックの範囲を縮小し、ロックが終了した後にタイムリーに解放することは、デッドロックを解決する方法であり、この例を通じて、私たちは後でコードを書くとロックの同期コードの範囲を警戒します.