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

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

目录

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

一、什么是死锁

二、死锁产生的条件

三、代码演示 

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();
    }
}

 

 

 

你可能感兴趣的:(线程死锁以及死锁解决的方法)