欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

线程死锁以及死锁解决的方法

程序员文章站 2022-04-17 14:05:12
...

线程死锁以及死锁解决的方法

目录

线程死锁以及死锁解决的方法

一、什么是死锁

二、死锁产生的条件

三、代码演示 

1. 死锁产生 

2. 调整加锁顺序避免死锁产生

3. 加锁时限避免死锁产生


一、什么是死锁

死锁是在两个以及两个以上线程在执行的过程中,由于资源竞争而出现的一种阻塞现象,如果没有外力作用,将会持续下去。

 

二、死锁产生的条件

  1. 互斥条件:每个锁资源一次只能有一个线程持有。
  2. 请求保持:线程拿着锁获取其他锁,并且不释放自己手中的锁。
  3. 不可剥夺:当一个线程没有自动释放锁之前,不可被动释放锁资源。
  4. 循环条件:多个线程由于资源竞争,形成的一种闭环。
     

三、代码演示 

1. 死锁产生 

public class DeadLockAction {
    /**
     * 三把锁
     */
    private static ReentrantLock lock1 = new ReentrantLock();
    private static ReentrantLock lock2 = new ReentrantLock();
    private static ReentrantLock lock3 = new ReentrantLock();

    public static void main(String[] args) {
        //线程1的加锁顺序 lock1 lock2 lock3
        Thread thread1 = new Thread(()->{
            lock1.lock();
            //为了提高死锁产生的次数 让线程睡眠5ms
            try {
                TimeUnit.MILLISECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            lock2.lock();lock3.lock();
            System.out.println("线程1拿到所有的锁");
            lock1.unlock();lock2.unlock();lock3.unlock();
        });
        //线程2的加锁顺序 lock2 lock3 lock1
        Thread thread2 = new Thread(()->{
            lock2.lock();
            try {
                TimeUnit.MILLISECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            lock3.lock();lock1.lock();
            System.out.println("线程2拿到所有的锁");
            lock2.unlock();lock3.unlock();lock1.unlock();
        });
        //线程3的加锁顺序 lock3 lock1 lock2
        Thread thread3 = new Thread(()->{
            lock3.lock();
            try {
                TimeUnit.MILLISECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            lock1.lock();lock2.lock();
            System.out.println("线程3拿到所有的锁");
            lock3.unlock();lock1.unlock();lock2.unlock();
        });

        thread1.start();thread2.start();thread3.start();
    }
}

2. 调整加锁顺序避免死锁产生

线程加锁的顺序必须按照某一顺序加锁,例如想获取锁3,必须先获得锁2,获取锁2,必须获得锁1,也就是加锁的顺序必须是锁1,锁2,锁3。调整加锁顺序的前提是需要与之需要的锁,但总是不可预知的。

public class DeadLockAction {
    /**
     * 三把锁
     */
    private static ReentrantLock lock1 = new ReentrantLock();
    private static ReentrantLock lock2 = new ReentrantLock();
    private static ReentrantLock lock3 = new ReentrantLock();

    public static void main(String[] args) {
        //线程1的加锁顺序 lock1 lock2 lock3
        Thread thread1 = new Thread(()->{
            lock1.lock();lock2.lock();lock3.lock();
            System.out.println("线程1拿到所有的锁");
            lock1.unlock();lock2.unlock();lock3.unlock();
        });
        //线程2的加锁顺序 lock1 lock2 lock3
        Thread thread2 = new Thread(()->{
            lock1.lock();lock2.lock();lock3.lock();
            System.out.println("线程2拿到所有的锁");
            lock1.unlock();lock2.unlock();lock3.unlock();
        });
        //线程3的加锁顺序 lock1 lock2 lock3
        Thread thread3 = new Thread(()->{
            lock1.lock();lock2.lock();lock3.lock();
            System.out.println("线程3拿到所有的锁");
            lock1.unlock();lock2.unlock();lock3.unlock();
        });

        thread1.start();thread2.start();thread3.start();
    }
}

3. 加锁时限避免死锁产生

加锁时,这只加锁的时间限制,超过某个时间得不到某个锁,就释放手中的所有的锁,隔段时间再次尝试加锁。

 

public class DeadLockAction {
    /**
     * 三把锁
     */
    private static ReentrantLock lock1 = new ReentrantLock();
    private static ReentrantLock lock2 = new ReentrantLock();
    private static ReentrantLock lock3 = new ReentrantLock();

    public static void main(String[] args) {
        //线程1的加锁顺序 lock1 lock2 lock3
        Thread thread1 = new Thread(()->{
            try {
                while(lock1.tryLock(1, TimeUnit.SECONDS)) {
                    //让死锁必产生
                    TimeUnit.MILLISECONDS.sleep(5);

                    if(lock2.tryLock(1, TimeUnit.SECONDS)){
                        if(lock3.tryLock(1, TimeUnit.SECONDS)){
                            System.out.println("线程1拿到所有的锁");
                            lock1.unlock();
                            lock2.unlock();
                            lock3.unlock();
                            //线程执行完毕退出
                            break;
                        }
                        //释放锁2
                        if(lock2.isHeldByCurrentThread()){
                            lock2.unlock();
                        }
                    }
                    //释放锁1
                    if(lock1.isHeldByCurrentThread()){
                        lock1.unlock();
                    }
                    //等待一段时间
                    TimeUnit.MILLISECONDS.sleep(100);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        });
        //线程2的加锁顺序 lock2 lock3 lock1
        Thread thread2 = new Thread(()->{
            try {
                while(lock2.tryLock(1, TimeUnit.SECONDS)) {
                    //让死锁必产生
                    TimeUnit.MILLISECONDS.sleep(5);

                    if(lock3.tryLock(1, TimeUnit.SECONDS)){
                        if(lock1.tryLock(1, TimeUnit.SECONDS)){
                            System.out.println("线程2拿到所有的锁");
                            lock1.unlock();
                            lock2.unlock();
                            lock3.unlock();
                            //线程执行完毕退出
                            break;
                        }
                        if(lock3.isHeldByCurrentThread()){
                            lock3.unlock();
                        }
                    }
                    if(lock2.isHeldByCurrentThread()){
                        lock2.unlock();
                    }
                    //等待一段时间
                    TimeUnit.MILLISECONDS.sleep(100);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        });

        //线程3的加锁顺序 lock3 lock1 lock2
        Thread thread3 = new Thread(()->{
            try {
                while(lock3.tryLock(1, TimeUnit.SECONDS)) {
                    //让死锁必产生
                    TimeUnit.MILLISECONDS.sleep(5);

                    if(lock1.tryLock(1, TimeUnit.SECONDS)){
                        if(lock2.tryLock(1, TimeUnit.SECONDS)){
                            System.out.println("线程3拿到所有的锁");
                            lock1.unlock();
                            lock2.unlock();
                            lock3.unlock();
                            //线程执行完毕退出
                            break;
                        }
                        if(lock1.isHeldByCurrentThread()){
                            lock1.unlock();
                        }
                    }
                    if(lock3.isHeldByCurrentThread()){
                        lock3.unlock();
                    }
                    //等待一段时间
                    TimeUnit.MILLISECONDS.sleep(100);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        });

        thread1.start();thread2.start();thread3.start();
    }
}