JavaインタビューのJUCシリーズ:デッドロックコーディングとポジショニング分析

デッドロックコーディングとロケーション分析

概念

デッドロックとは、実行プロセス中のリソースの競合により、2つ以上のプロセスが互いに待機する現象を指します。外部からの干渉がない場合、プロセスは進行できません。リソースが十分であれば、プロセスのリソース要求を満たすことができ、デッドロックの可能性は非常に低くなります。そうでない場合、限られたリソースの競合によりデッドロックに陥ります。

画像-20200318175441578

デッドロックの原因

  • 不十分なシステムリソース
  • プロセスが実行されている順序が正しくありません
  • リソースの誤割り当て

デッドロックの4つの必要条件

  • 相互に排他的
    • 解決策:相互に排他的な共有リソースを同時アクセスにカプセル化する
  • 待ってください
    • 解決策:プロセスがリソースを要求する場合、他のリソースを占有しないようにする必要があります。つまり、すべてのリソースに一度に適用する必要があります。この方法では、リソースの効率が低下します。
  • 非プリエンプティブ
    • 解決策:プロセスがリソースをすぐに割り当てることができない場合は、他のリソースを占有しないようにする必要があります。つまり、必要なすべてのリソースを同時に取得できる場合にのみ、割り当て操作を実行できます。
  • ループ待機
    • 解決策:リソースを並べ替え、プロセスにリソースを順番に要求するように要求します。

デッドロックコード

リソースクラスを作成し、2つのスレッドに独自のロックを保持させ、同時に他のスレッドを取得しようとすると、デッドロック現象が発生します

/**
 * 死锁小Demo
 * 死锁是指两个或多个以上的进程在执行过程中,
 * 因争夺资源而造成一种互相等待的现象,
 * 若无外力干涉那他们都将无法推进下去
 */

import java.util.concurrent.TimeUnit;

/**
 * 资源类
 */
class HoldLockThread implements Runnable{
    
    

    private String lockA;
    private String lockB;

    // 持有自己的锁,还想得到别人的锁

    public HoldLockThread(String lockA, String lockB) {
    
    
        this.lockA = lockA;
        this.lockB = lockB;
    }


    @Override
    public void run() {
    
    
        synchronized (lockA) {
    
    
            System.out.println(Thread.currentThread().getName() + "\t 自己持有" + lockA + "\t 尝试获取:" + lockB);

            try {
    
    
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }

            synchronized (lockB) {
    
    
                System.out.println(Thread.currentThread().getName() + "\t 自己持有" + lockB + "\t 尝试获取:" + lockA);
            }
        }
    }
}
public class DeadLockDemo {
    
    
    public static void main(String[] args) {
    
    
        String lockA = "lockA";
        String lockB = "lockB";

        new Thread(new HoldLockThread(lockA, lockB), "t1").start();

        new Thread(new HoldLockThread(lockB, lockA), "t2").start();
    }
}

実行した結果、メインスレッドを終了できません

t1	 自己持有lockA	 尝试获取:lockB
t2	 自己持有lockB	 尝试获取:lockA

デッドロックのトラブルシューティング方法

デッドロックが発生した場合、最初にjpsコマンドを使用して実行中のプログラムを表示する必要があります

jps -l

実行されているDeadLockDemoクラスを見ることができます

画像-20200318181504703

jstackを使用してスタック情報を表示する

jstack  7560   # 后面参数是 jps输出的该类的pid

得られた結果

Found one Java-level deadlock:
=============================
"t2":
  waiting to lock monitor 0x000000001cfc0de8 (object 0x000000076b696e80, a java.lang.String),
  which is held by "t1"
"t1":
  waiting to lock monitor 0x000000001cfc3728 (object 0x000000076b696eb8, a java.lang.String),
  which is held by "t2"

Java stack information for the threads listed above:
===================================================
"t2":
        at com.moxi.interview.study.Lock.HoldLockThread.run(DeadLockDemo.java:42)
        - waiting to lock <0x000000076b696e80> (a java.lang.String)
        - locked <0x000000076b696eb8> (a java.lang.String)
        at java.lang.Thread.run(Thread.java:745)
"t1":
        at com.moxi.interview.study.Lock.HoldLockThread.run(DeadLockDemo.java:42)
        - waiting to lock <0x000000076b696eb8> (a java.lang.String)
        - locked <0x000000076b696e80> (a java.lang.String)
        at java.lang.Thread.run(Thread.java:745)

Found 1 deadlock.

最後の行を見ると、Found 1デッドロックがあります。つまり、デッドロックがあります。

おすすめ

転載: blog.csdn.net/weixin_43314519/article/details/110283277