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

响应中断的锁

在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);

你可能感兴趣的:(java,多线程)