通过排序避免死锁

Java 9并发编程指南 目录

当需要在应用方法中获取多个锁时,必须非常小心控制锁的顺序,错误的选择会导致死锁情形。

本节将实现死锁情形的范例,然后学习如何解决死锁。

实现过程

通过如下步骤实现本范例:

  1. 创建名为BadLocks的类,包含两个方法,名为operation1()和operation2():

    public class BadLocks {
        private Lock lock1, lock2;
        public BadLocks(Lock lock1, Lock lock2) {
            this.lock1=lock1;
            this.lock2=lock2;
        }
        public void operation1(){
            lock1.lock();
            lock2.lock();
            try {
            	TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
           	 e.printStackTrace();
            } finally {
                lock2.unlock();
                lock1.unlock();
            }
        }
        public void operation2(){
            lock2.lock();
            lock1.lock();
            try {
            	TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
            	e.printStackTrace();
            } finally {
                lock1.unlock();
                lock2.unlock();
            }
        }
    }
    
  2. 分析下这段代码,如果线程调用operation1()方法,并且另一个线程调用operation2()方法,则造成死锁。如果operation1()和operation2()同时执行各自的第一行代码,operation1()方法等待控制lock2,而operation2()方法等待控制lock1。 这就造成了死锁情形。

  3. 为了解决死锁,遵循如下规则:

    • 如果必须在不同的操作中控制多个锁,试图在所有方法中以相同的顺序锁定它们。
    • 然后,按照相反的顺序释放锁,并将锁及其解锁封装在一个类中。这样就不会在整个代码中分布与同步相关的代码。

工作原理

使用此规则,将避免死锁情形。例如本范例中,改变operation2()方法,首先得到lock1,然后lock2。现在如果operation1()和operation2()同时执行各自的第一行代码,其中一个方法将被阻塞等待lock1,另一个方法得到lock1和lock2,并执行操作。之后被阻塞的线程将获得lock1和lock2锁,并执行其操作。

扩展学习

开发过程中,可能会出现在所有操作中阻止按照相同顺序获取锁的情况,这时需要使用Lock类的tryLock()方法。此方法返回Boolean值,指明是否具有锁的控制权。使用tryLock()方法尝试获取执行操作需要的所有锁。如果无法控制其中一个锁,则必须释放可能拥有的所有锁,并重新启动操作。

更多关注

  • 本章“保持锁的时间尽可能短”小节
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值