死锁的成因及解决方案

死锁的三种条件

1.一个线程一把锁

当一个线程尝试重复获取锁,如果该锁不是可重入锁,则会尝生死锁

(图中的synchronized是可重入锁)

public class Demotest {

    public static void main(String[] args) {

     Object lock=new Object();
     synchronized (lock){
         synchronized (lock)
         {
             while(true)
             {
                 System.out.println("Hello");
             }
         }
     }
     
    }
}

2.两个线程两把锁

当A获取到锁1,B获取到锁2

而A尝试获取锁2,B尝试获取锁1,产生死锁

public class Demotest {

    public static void main(String[] args) {

     Object lock1=new Object();
     Object lock2=new Object();
     
     Thread t1=new Thread(()->
     {
         synchronized (lock1)
         {
             try {
                 Thread.sleep(1000);
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }
             synchronized (lock2){
                 System.out.println("t1");
             }
         }
         
     });
     
        Thread t2=new Thread(()->
        {
            synchronized (lock2)
            {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (lock1){
                    System.out.println("t2");
                }
            }

        });
        
        
        t1.start();
        t2.start();
    }
}

3.N个线程N把锁

哲学家就餐问题

:五个哲学家围坐在一张桌子附近,每人前面有一碗意面,共有五把叉子,每个哲学家需要左右手 同时拿起叉子才能就餐,且哲学家会在思考和就餐这两种状态进行交替。当五个哲学家同时拿起右手边的叉子,当准备去拿左手边的叉子时,就会造成死锁的情况。


死锁产生的四个必要条件

1.互斥使用:该资源任意时刻只由一个线程占有。

2.不可抢占:该线程使用资源过程中不能被其它线程所剥夺,只有使用完后才能释放资源。

3.请求和保持:该线程因其它请求资源而阻塞的时候,保持对原有资源的占有。

4.循环等待:若干线程形成首尾相接的循环等待资源的关系。

其中循环等待是最容易出现的问题

打破循环等待的方法:给锁进行编号,当多把锁的时候,约定锁的顺序,如以下代码就产生了循环等待。

public class Demotest {

    public static void main(String[] args) {

     Object lock1=new Object();
     Object lock2=new Object();

     Thread t1=new Thread(()->
     {
         synchronized (lock1)
         {
             try {
                 Thread.sleep(1000);
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }
             synchronized (lock2){
                 System.out.println("t1");
             }
         }

     });

        Thread t2=new Thread(()->
        {
            synchronized (lock2)
            {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (lock1){
                    System.out.println("t2");
                }
            }

        });

        
        t1.start();
        t2.start();
    }
}

将代码改为即可

public class Demotest {

    public static void main(String[] args) {

     Object lock1=new Object();
     Object lock2=new Object();

     Thread t1=new Thread(()->
     {
         synchronized (lock1)
         {
             try {
                 Thread.sleep(1000);
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }
             synchronized (lock2){
                 System.out.println("t1");
             }
         }

     });

        Thread t2=new Thread(()->
        {
            synchronized (lock1)
            {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (lock2){
                    System.out.println("t2");
                }
            }

        });


        t1.start();
        t2.start();
    }
}

                
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值