引言
上一节介绍了 ReentrantLock 类的 lock 锁获取流程,本节继续来说说它的其他两个知识点:
- lock 和 lockInterruptibly 的区别
- newCondition() ,条件队列的实现逻辑
lock 和 lockInterruptibly 的区别
ReentrantLock 的 lock 方法有几种获取锁方式:
- tryLock(),tryLock(long ,TimeUnit) ,可轮询的、可定时地获取锁;
- lock() ,无条件地轮询获取锁,锁等待期间,线程可被中断;
- lockInterruptibly() ,可中断的锁获取方式,锁等待期间,线程可被中断。
lock() 和 lockInterruptibly() ,这两个方法都能响应中断请求,但是区别在哪里呢?
分析源码,笔者发现 lock 方法默认处理了中断请求,一旦监测到中断状态,则中断当前线程;而 lockInterruptibly() 则直接抛出中断异常,由上层调用者区去处理中断,一起来看看源码细节。
lock 源码
lock 方法在获取锁的过程中,忽略了中断,并在成功获取锁之后,再根据中断标识处理中断,即 selfInterrupt 中断自己。 再回忆下 acquire 的源码:
/** *默认处理中断方式是selfInterrupt */public final void acquire(int arg) { if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt();}
acquireQueued,在 for 循环中无条件重试获取锁,直到成功,同时返回线程中断状态。for 循正常返回时,必定是成功获取到了锁,它的源码是这样:
/** *无条件重试,直到成功返回,并且记录中断状态 */final boolean acquireQueued(final Node node, int arg) { boolean failed = true; try { boolean interrupted = fa