多线程之死锁分析

Posted Java硅谷

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多线程之死锁分析相关的知识,希望对你有一定的参考价值。

        在多线程操作过程中,我们难免会遇到资源加锁,保证共享资源的安全性,不免有时会遇到死锁的问题。现在我们就一个简单的实例代码对死锁问题进行剖析,抛砖引玉。

案例:

public class OtherService {

    DeadLock deadLock;

    public void setDeadLock(DeadLock deadLock){
        this.deadLock = deadLock;
    }

    private final Object LOCK = new Object();

    public void s1(){
        synchronized (LOCK){
            System.out.println("s1----------------------------");
        }

    }

    public void s2(){
        synchronized (LOCK){
            System.out.println("s2----------------------------");
            deadLock.m2();
        }

    }
}
public class DeadLock {

    private OtherService otherService;

    public DeadLock(OtherService otherService){
        this.otherService = otherService;
    }
    private final Object LOCK = new Object();

    public void m1(){
        synchronized (LOCK){
            System.out.println("m1-----------------------");
            otherService.s1();
        }
    }

    public void m2(){
        synchronized (LOCK){
            System.out.println("m2-----------------");
        }
    }

}

测试类:

public class DeadLockTest {

    public static void main(String[] args) {
        OtherService otherService = new OtherService();
        DeadLock deadLock = new DeadLock(otherService);
        otherService.setDeadLock(deadLock);

        new Thread(()->{
            while (true){
                deadLock.m1();
            }
        }).start();

        new Thread(()->{
            while (true){
                otherService.s2();
            }
        }).start();

    }
}

观察测试案例,可以知道,我们测试类中对OtherService和DeadLock相互持有,模拟一个死锁状态,当两个线程执行到某一个状态的时候,OtherService和DeadLock就会达到互斥的状态,占锁不放并且想要获取的锁拿不到,从而达到死锁状态。

分析:

我们可以利用jdk的命令查看线程的状态:

jstack  [进程号]

F:\Study_>jstack 2788
2018-04-10 13:04:54
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.131-b11 mixed mode):

"DestroyJavaVM" #13 prio=5 os_prio=0 tid=0x0000000004c7e000 nid=0x196c waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Thread-1" #12 prio=5 os_prio=0 tid=0x000000001b793000 nid=0x17d0 waiting for monitor entry [0x000000001c1de000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at com.thread.thred.dead.DeadLock.m2(DeadLock.java:21)
        - waiting to lock <0x00000000d5d93040> (a java.lang.Object)
        at com.thread.thred.dead.OtherService.s2(OtherService.java:25)
        - locked <0x00000000d5d90558> (a java.lang.Object)
        at com.thread.thred.dead.DeadLockTest.lambda$main$1(DeadLockTest.java:18)
        at com.thread.thred.dead.DeadLockTest$$Lambda$2/1831932724.run(Unknown Source)
        at java.lang.Thread.run(Thread.java:748)

"Thread-0" #11 prio=5 os_prio=0 tid=0x000000001b792800 nid=0x226c waiting for monitor entry [0x000000001c0df000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at com.thread.thred.dead.OtherService.s1(OtherService.java:17)
        - waiting to lock <0x00000000d5d90558> (a java.lang.Object)
        at com.thread.thred.dead.DeadLock.m1(DeadLock.java:15)
        - locked <0x00000000d5d93040> (a java.lang.Object)
        at com.thread.thred.dead.DeadLockTest.lambda$main$0(DeadLockTest.java:12)
        at com.thread.thred.dead.DeadLockTest$$Lambda$1/990368553.run(Unknown Source)
        at java.lang.Thread.run(Thread.java:748)

从线程状态可以看出,Thread-0和Thread-1已经是死锁状态。

死锁发生的条件是:

 互斥条件(Mutual exclusion)     :资源不能被共享,只能由一个进程使用。
     请求与保持条件(Hold and wait)进程已获得了一些资源,但因请求其它资源被阻塞时,对已获得的资源保持不放
     不可抢占条件(No pre-emption)    :有些系统资源是不可抢占的,当某个进程已获得这种资源后,系统不能强行收回,只能由进程使用完时自己释放
     循环等待条件(Circular wait)      :若干个进程形成环形链,每个都占用对方申请的下一个资源


以上是关于多线程之死锁分析的主要内容,如果未能解决你的问题,请参考以下文章

iOS底层探索之多线程—GCD源码分析(死锁的原因)

使用Windbg分析多线程临界区死锁问题分享

使用Windbg分析多线程临界区死锁问题分享

java多线程同步以及线程间通信详解&消费者生产者模式&死锁&Thread.join()(多线程编程之二)

多线程等待唤醒机制之生产消费者模式

怎么处理JAVA多线程死锁问题?