响应中断的锁与定时锁的实现原理

来源:互联网 发布:在管委会上班好吗知乎 编辑:程序博客网 时间:2024/04/30 01:32

响应中断的锁

在JDK5之前使用Synchronized作为获取锁的关键字,但是在获取锁的过程中无法中断,及时调用Thread.interrupt也不会中断。
为了能够使线程快速的响应中断,可以使用lock.lockInterruptibly方法。

通过源码分析可中断的锁

ReentrantLock的lockInterruptibly的基本使用

public static void main(String[] args) throws InterruptedException {        ReentrantLock lock = new ReentrantLock(true);        Thread t1 =     new Thread(new Runnable() {            @Override            public void run() {                try {                    TimeUnit.SECONDS.sleep(1);                    System.out.println("我是终端锁,在等待被中断");                    lock.lockInterruptibly();//此处如果是lock.lock(),及时线程2来中断也不会做任何响应.                    System.out.println("如果我出现,则代表,我不能相应终端");                } catch (InterruptedException e) {                    e.printStackTrace();                    System.out.println("我被打断了");                } finally {                    lock.unlock();                }            }        });        t1.start();        Thread t2 =     new Thread(new Runnable() {            @Override            public void run() {                try {                    lock.lock();                    System.out.println(new Date() + ":我要睡5秒");                    TimeUnit.SECONDS.sleep(5);                    System.out.println("开始打断线程1");                    t1.interrupt();                    TimeUnit.SECONDS.sleep(3);                    System.out.println("已经打断了线程1");                } catch (InterruptedException e) {                    e.printStackTrace();                } finally {                    lock.unlock();                }            }        });        t2.start();    }

线程1使用lock.lockInterruptibly(),当该线程获取不到锁的时候,阻塞。
线程2先获得锁,此时去中断线程1,线程1相应中断抛出异常。

源码分析lockInterruptibly方法

lock()底层使用AQS的acquireQueued方法。
lock.lockInterruptibly() 底层使用AQS的doAcquireInterruptibly
方法。
acquireQueued和doAcquireInterruptibly的唯一不同是,当出现中断后,doAcquireInterruptibly会抛出异常:

if (shouldParkAfterFailedAcquire(p, node) &&        parkAndCheckInterrupt())        throw new InterruptedException();

到此为止我们总共介绍了AQS中的:
1. 排它锁
2. 共享锁
3. Condition
4. 可相应中断的锁
最后还有一个,5. 定时锁
tryLock(long timeout, TimeUnit unit)
在这里就不再介绍了,实际上就是AQS中doAcquireNanos的实现,相比lock,设置了一个锁的时长 LockSupport.parkNanos(this, nanosTimeout);

0 0