关于死锁(死锁的演示、产生原因以及如何解决死锁等)

一、死锁示例

代码演示:

执行结果:

 我们通过jconsole工具再来看一次

​通过jvsualvm也可以观察(也是在jdk的bin目录下):

还可以通过jmc来观察:

总结:

二、死锁产生原因

三、如何解决死锁? 


一、死锁示例

代码演示:

package thread.threaddemo;

import java.util.concurrent.TimeUnit;

/**
 * @Author: wenjingyuan
 * @Date: 2022/11/20/11:05
 * @Description:死锁示例
 */
public class ThreadDemo18 {
    public static void main(String[] args) {
        Object lockA=new Object();
        Object lockB=new Object();
        Thread t1=new Thread(()->{
           synchronized (lockA){
               System.out.println("线程1获得了A");
               try {
                   TimeUnit.SECONDS.sleep(1);
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
               synchronized (lockB){
                   System.out.println("线程1或得到B");
               }
           }
        });
        t1.start();

        Thread t2=new Thread(()->{
            synchronized (lockB){
                System.out.println("线程2获得了B");
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (lockA){
                    System.out.println("线程2或得到A");
                }
            }
        });
        t2.start();
    }
}

执行结果:

 我们通过jconsole工具再来看一次

 通过jvsualvm也可以观察(也是在jdk的bin目录下):

还可以通过jmc来观察:

这里我们将不做详细的叙述!

总结:

两个线程在拥有锁的情况下,在尝试获取对方的锁,从而导致程序进入阻塞状态

二、死锁产生原因

1.互斥问题

一个资源只能被一个线程占有,当这个资源被占用以后其他的线程只能等待

2.不可被剥夺条件

当一个线程占用一个资源的时候,如果不主动释放资源这个资源就只能被一直占用

3.请求并持有条件

当线程拥有某个资源的时候,还不满足,又在请求其他的资源

4.环路等待条件

多个线程在请求资源的时候形成环路链

注意:发生死锁并不是说这四个其中一个的因素,是四个因素共同导致了死锁!(缺一不可)

三、如何解决死锁? 

思路:打破形成死锁的一个或者多个条件即可!

首先我们分析可知,条件中的三四是人为可以修改的。

1.我们先进行改变条件三,请求并持有条件。

代码如下:

package thread.threaddemo;

import java.util.concurrent.TimeUnit;

/**
 * @Author: wenjingyuan
 * @Date: 2023/01/14/19:04
 * @Description:解决死锁,破坏请求并持有条件
 */
public class UnDeadLock {
    public static void main(String[] args) {
        Object lockA=new Object();
        Object lockB=new Object();
        Thread t1=new Thread(()->{
            synchronized (lockA){
                System.out.println("线程1拿到了锁A");
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
//                synchronized (lockB){
//                    System.out.println("线程1拿到了锁B");
//                    //业务代码
//                    System.out.println("线程1释放了锁B");
//                }
                System.out.println("线程1释放了锁A");
            }
        },"线程1");
        t1.start();

        Thread t2=new Thread(()->{
            synchronized (lockB){
                System.out.println("线程2拿到了锁B");
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
//                synchronized (lockA){
//                    System.out.println("线程2拿到了锁A");
//                    //业务代码
//                    System.out.println("线程2释放了锁A");
//                }
                System.out.println("线程2释放了锁B");
            }
        },"线程2");
        t2.start();
    }
}

运行结果如下:

2.接下来我们改变条件四,改变环路条件(也叫做使用顺序锁解决死锁问题),代码如下:

package thread.threaddemo;

import java.util.concurrent.TimeUnit;

/**
 * @Author: wenjingyuan
 * @Date: 2023/01/14/19:04
 * @Description:解决死锁,破坏环路等待条件
 */
public class UnDeadLock2 {
    public static void main(String[] args) {
        Object lockA=new Object();
        Object lockB=new Object();
        Thread t1=new Thread(()->{
            synchronized (lockA){
                System.out.println("线程1拿到了锁A");
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (lockB){
                    System.out.println("线程1拿到了锁B");
                    //业务代码
                    System.out.println("线程1释放了锁B");
                }
                System.out.println("线程1释放了锁A");
            }
        },"线程1");
        t1.start();

        Thread t2=new Thread(()->{
            synchronized (lockA){
                System.out.println("线程2拿到了锁A");
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (lockB){
                    System.out.println("线程2拿到了锁B");
                    //业务代码
                    System.out.println("线程2释放了锁B");
                }
                System.out.println("线程2释放了锁A");
            }
        },"线程2");
        t2.start();
    }
}

 运行结果如下:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值