美文网首页
Java基础->死锁

Java基础->死锁

作者: 杨0612 | 来源:发表于2020-09-18 10:35 被阅读0次
什么是死锁?

多个线程因竞争同一个资源而造成互相等待的状态,在没有外力的作用下,线程将处于永远等待,这就是死锁。

死锁例子 - 嵌套同步代码
public class Test {
    public Object mLock1 = new Object();
    public Object mLock2 = new Object();
    public void test1() {
        synchronized (mLock1) {
            //do something
            synchronized (mLock2) {
                //do something
            }
        }
    }

    public void test2() {
        synchronized (mLock2) {
            //do something
            synchronized (mLock1) {
                //do something
            }
        }
    }
}

场景:线程A 执行test1方法,获取mLock1锁进入同步代码,线程B执行test2方法,获取mLock2锁进入同步代码,这时线程A竞争mLock2锁,发现锁被线程B持有,则线程A同步阻塞,与此同时,线程B竞争mLock1锁,发现锁被线程A持有,则线程B同步阻塞。线程A持有mLock1锁,等待mLock2,线程B持有mLock2,等待mLock1,在没有外力的作用下,线程A、线程B永远处于等待状态,死锁就发生了

如何解决该类死锁问题
  • 保持请求锁顺序一致;
    代码如下,test1、test2都是先请求mLock1,后请求mLock2,这样就不会出现相互持有的情况。
public class Test {
    public Object mLock1 = new Object();
    public Object mLock2 = new Object();
    public void test1() {
        synchronized (mLock1) {
            //do something
            synchronized (mLock2) {
                //do something
            }
        }
    }

    public void test2() {
        synchronized (mLock1) {
            //do something
            synchronized (mLock2) {
                //do something
            }
        }
    }
}
  • 不要嵌套同步代码,将同步代码的范围缩小;
    代码如下,将test1拆分成test1和test3,将test2拆分test2和test4,在外部通过非同步方法调用来达到目的。
public class Test {
    public Object mLock1 = new Object();
    public Object mLock2 = new Object();
    public void test1() {
        synchronized (mLock1) {
           //do something1
          }
     }

    public void test3() {
        synchronized (mLock2) {
            //do something3
        }
    }
    

    public void test2() {
        synchronized (mLock2) {
             //do something2
        }
    }

    public void test4() {
        synchronized (mLock1) {
            //do something4
        }
    }
}
  • 增加请求锁超时;
    利用ReentrantLock的tryLock(1000,TimeUnit.SECONDS)方法,判断一定时间内是否能获取锁成功,成功则执行任务,否则释放自己持有的锁。

代码如下,test1在请求lock2 锁的是时候,设置了超时,如果在时间范围内没有获取到,则执行别的任务,结束方法释放lock1,test2方法同理;

public class Test {
    public ReentrantLock lock1 = new ReentrantLock();
    public ReentrantLock lock2 = new ReentrantLock();

    public void test1() {
        lock1.lock();//lock1加锁
        //do something      
        boolean isLock = false;
        try {
            isLock = lock2.tryLock(1000, TimeUnit.SECONDS);
            if (isLock) {//执行获取了锁的任务
                //do something
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (isLock) {
                lock2.unlock();
            }
        }
        lock1.unlock();//lock1释放锁
    }


    public void test2() {
        lock2.lock();//lock2加锁
        //do something
   
        boolean isLock = false;
        try {
            isLock = lock1.tryLock(1000, TimeUnit.SECONDS);
            if (isLock) {//执行获取了锁的任务
                //do something
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (isLock) {
                lock1.unlock();
            }
        }

        lock2.unlock();//lock2加锁
    }
}
如何发现该类死锁问题?

加强编码规范以及review代码,当发现类似的嵌套同步代码、获取锁顺序不一致,就得留意是否会出现死锁问题。

总结

当发现有嵌套同步代码时,可以通过保持请求锁顺序一致、不要嵌套同步代码,将同步代码的范围缩小、增加请求锁超时方法,解决死锁问题。
以上解决方案,不是完整的代码,只是提供了大致的方法,需要根据业务情况来修改代码。

以上分析有不对的地方,请指出,互相学习,谢谢哦!

相关文章

  • Java基础->死锁

    什么是死锁? 多个线程因竞争同一个资源而造成互相等待的状态,在没有外力的作用下,线程将处于永远等待,这就是死锁。 ...

  • Java基础之死锁

    死锁是多线程中的常见问题,那么我们就来看看死锁的相关内容。本文的要点如下: 定义 产生的条件 类型 总结 定义 死...

  • Java死锁检测之ThreadMXBean

    看此文章前请先了解之前一篇文章 "Java死锁之理解死锁" 中的死锁示例java 中提供了可以检测死锁的工具类Th...

  • Java基础-线程-线程死锁

    Java工程师知识树[https://www.jianshu.com/p/db77d19a25f6] / Ja...

  • Java concurrency《防止死锁》

    Java concurrency《防止死锁》 常见预防死锁的办法 有顺序的锁 具有超时时间的锁 死锁的检测 有顺序...

  • 如何去检测死锁

    如何检测死锁 死锁预防 让线程获取锁的顺序一致 死锁检测 jps 查看java 进程信息 jstack +进程号 ...

  • 死锁

    在JAVA编程中,有3种典型的死锁类型: 静态的锁顺序死锁 动态的锁顺序死锁 协作对象之间发生的死锁 静态的锁顺序...

  • Java死锁的简单例子

    Java死锁的简单例子 两个线程互相占有对方需要的资源而不释放,便形成了死锁。 代码如下:Program.java...

  • JVM_JMM: 死锁的检测

    死锁的示例代码: 通过jconsole来检测死锁: 名称: Thread-1状态: java.lang.Class...

  • java死锁介绍、源码实现及预防(含源码)

    java死锁介绍、源码实现及预防(含源码) 什么是死锁 死锁是 多个线程 之间 相互之间 持有 对方需要的资源,同...

网友评论

      本文标题:Java基础->死锁

      本文链接:https://www.haomeiwen.com/subject/qgklyktx.html