死锁的产生原因以及解决方案

Posted 不会秃头的小齐

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了死锁的产生原因以及解决方案相关的知识,希望对你有一定的参考价值。

目录

1、什么是死锁

2、死锁的代码展示

3、死锁产生的原因

4、如何解决死锁问题


1、什么是死锁

死锁就是两个或两个以上线程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。

2、死锁的代码展示

也就是两个线程在各自拥有锁的情况下,又去尝试获取对方的锁,从而造成的一直阻塞的情况。

public class Thread18 
    public static void main(String[] args) 
        Object lockA = new Object();
        Object lockB = new Object();

        Thread t1 = new Thread(() -> 
            // 1.占有一把锁(锁A)
            synchronized (lockA) 
                System.out.println("线程1:获得锁A。");
                // 休眠 1s(让线程2有时间先占有锁B)
                try 
                    TimeUnit.SECONDS.sleep(1);
                 catch (InterruptedException e) 
                    e.printStackTrace();
                
                // 2.获取线程2的锁B
                synchronized (lockB) 
                    System.out.println("线程1:获得锁B。");
                
            
        );
        t1.start();

        Thread t2 = new Thread(() -> 
            // 1.占有一把锁(锁B)
            synchronized (lockB) 
                System.out.println("线程2:获得了锁B!");
                // 休眠1s(保证线程1能有充足的时间得到锁A)
                try 
                    TimeUnit.SECONDS.sleep(1);
                 catch (InterruptedException e) 
                    e.printStackTrace();
                
                // 2.获取线程1的锁A
                synchronized (lockA) 
                    System.out.println("线程2:获得了锁A!");
                
            
        );
        t2.start();

    

3、死锁产生的原因

①互斥条件:一个资源只能被一个线程占有,当这个资源被占用后其他线程就只能等待。

②不可剥夺条件:当一个线程不主动释放资源时,此资源一直被拥有线程占有。

③请求并持有条件:线程已经拥有一个资源后仍然不满足,又尝试请求新的资源。

④环路等待条件:产生死锁一定是发生了线程资源环路链。

4、如何解决死锁问题

改变死锁中的任意一个或多个条件就可以解决死锁问题,其中被修改的条件只有后两个:请求并持有条件和环路等待条件。

修改请求并持有条件:获得了一把锁之后不再去请求获取另一把锁

破坏环路等待条件:如果就是需要两把锁的资源,则可以按照如下流程进行操作:

 ①线程1得到锁A,线程②进入阻塞状态。

②线程1去获取锁B,此时线程2仍然处于阻塞状态。

③线程1执行完毕,释放锁B,释放锁A。

④线程2获得锁A,继续执行。

⑤线程2获得锁B。

⑥线程2释放锁B。

⑦线程2释放锁A,执行结束。

实现代码:

/**
 * 解决死锁方案:破坏环路等待条件
 */
public class UnDeadLock2 
    public static void main(String[] args) 
        Lock lockA = new ReentrantLock();
        Lock lockB = new ReentrantLock();
        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();
    

以上是关于死锁的产生原因以及解决方案的主要内容,如果未能解决你的问题,请参考以下文章

死锁产生的原因以及解决方法

java 死锁产生原因及解锁(转)

试述死锁产生的原因和解决办法

java 多线程-死锁的产生以及解决方案

多线程死锁的产生原因以及如何避免

java 死锁