美文网首页
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基础->死锁

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