被遗忘的凉白开
文章22
标签34
分类3
面试官:死锁说的不错,活锁听说过么?

面试官:死锁说的不错,活锁听说过么?

有死锁,也就有活锁,活锁的情况我们在使用尝试拿锁机制里是有很大的几率发生的,如何避免活锁的发生,也是很重要的!

这是我参与更文挑战的第15天,活动详情查看: 更文挑战

面试官又问了:什么是死锁?
这篇文章是在 死锁的概念上开始讲的,不懂死锁是怎么回事的,请到开头找链接,先去学习一下死锁

在上一篇文章中我们已经讲过了,构成死锁的三个条件,其中有一个条件就是拿到资源不放手!,但是我们有没有一种机制,在拿到资源之后释放锁呢?

在Java里面有一个Lock接口
Lock接口里的方法

image.png

里面有拿锁中可以中断的方法,还有一个tryLock尝试拿锁机制,unlock方法释放锁,我们用一段代码,用尝试拿锁机制来破解死锁问题

public class TryLock {
    private static Lock No13 = new ReentrantLock();//第一个锁
    private static Lock No14 = new ReentrantLock();//第二个锁

    //先尝试拿No13 锁,再尝试拿No14锁,No14锁没拿到,连同No13 锁一起释放掉
    private static void fisrtToSecond() throws InterruptedException {
        String threadName = Thread.currentThread().getName();
        Random r = new Random();
        while(true){
            if(No13.tryLock()){
                System.out.println(threadName
                        +" get 13");
                try{
                    if(No14.tryLock()){
                        try{
                            System.out.println(threadName
                                    +" get 14");
                            System.out.println("fisrtToSecond do work------------");
                            break;
                        }finally{
                            No14.unlock();
                        }
                    }
                }finally {
                    No13.unlock();
                }

            }
            //Thread.sleep(r.nextInt(3));
        }
    }

    //先尝试拿No14锁,再尝试拿No13锁,No13锁没拿到,连同No14锁一起释放掉
    private static void SecondToFisrt() throws InterruptedException {
        String threadName = Thread.currentThread().getName();
        Random r = new Random();
        while(true){
            if(No14.tryLock()){
                System.out.println(threadName
                        +" get 14");
                try{
                    if(No13.tryLock()){
                        try{
                            System.out.println(threadName
                                    +" get 13");
                            System.out.println("SecondToFisrt do work------------");
                            break;
                        }finally{
                            No13.unlock();
                        }
                    }
                }finally {
                    No14.unlock();
                }

            }
            //Thread.sleep(r.nextInt(3));
        }
    }

    private static class TestThread extends Thread{

        private String name;

        public TestThread(String name) {
            this.name = name;
        }

        public void run(){
            Thread.currentThread().setName(name);
            try {
                SecondToFisrt();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        Thread.currentThread().setName("TestDeadLock");
        TestThread testThread = new TestThread("SubTestThread");
        testThread.start();
        try {
            fisrtToSecond();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

上面的代码中 ,两个线程如果第一次都拿到了相应的锁,第二次拿锁的时候拿不到的话就把连同第一次的锁释放掉,这样其他线程就有拿到锁的可能了,

上面的代码,注释了两行代码线程休眠随机的时间,为什么要加这两个方法,其目的就是为了错开拿锁的时间,增大我把这把锁释放掉,被另一个线程拿到的可能性

如果我们不加 线程休眠的方法,很有可能发生一种情况,两个线程同时,一个拿到13号锁 一个拿到14号锁,然后又同时把他们释放掉,又同时,一个拿到了13号锁,一个拿到14号锁,又同时释放掉锁,形成了一个循环,两个线程一直在苦逼的拿锁释放锁,而不干任何事情!这个就是传说中的活锁了!而死锁呢,是完全被阻塞那里了,像死了一样!

image.png

以上就是对活锁的描述!希望内容对XDM有帮助,XDM给个三连!

本文作者:被遗忘的凉白开
本文链接:http://amszlk.com/2021/06/24/mian-shi-guan-si-suo-shuo-de-bu-cuo-huo-suo-ting-shuo-guo-me/
版权声明:本文采用 CC BY-NC-SA 3.0 CN 协议进行许可