Condition 实现原理
Object 中可以通过 wait() 、notify() 来休眠唤醒。Condition 中同样可以实现这样的效果。
static ReentrantLock lock = new ReentrantLock(); static Condition condition = lock.newCondition(); public static void main(String[] args) throws Exception{ new Thread(()->{ lock.lock(); System.out.println("阻塞前的逻辑"); try { condition.await(); }catch (Exception e){ e.printStackTrace(); } System.out.println("阻塞后的逻辑"); lock.unlock(); }).start(); Thread.sleep(2000L); new Thread(()->{ lock.lock(); System.out.println("唤醒线程"); condition.signal(); lock.unlock(); }).start(); }
await
public final void await() throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); //1. 当前线程将自己加入condition等待队列 Node node = addConditionWaiter(); //2. 挂起线程前,必须释放当前锁 int savedState = fullyRelease(node); int interruptMode = 0; // 这里搞了个标志 //3. 判断当前线程是否在同步队列中,如果不在同步队列,则直接挂起线程 while (!isOnSyncQueue(node)) { LockSupport.park(this); // 如果线程被唤醒,线程节点从条件队列移除(就是cas将当前状态从-2改成0),并放到放到同步队列,或被中断 if ((interruptMode = checkInterruptWhileWaiting(node)) != 0) break; } //4. 唤醒之后进入同步队列去竞争锁 // 获取锁时中断,并且标志不是(响应中断) if (acquireQueued(node, savedState) && interruptMode != THROW_IE) interruptMode = REINTERRUPT; if (node.nextWaiter != null) // clean up if cancelled //5. 清除等待队列中不是等待状态的节点 unlinkCancelledWaiters(); //6. 处理被中断的逻辑 if (interruptMode != 0) reportInterruptAfterWait(interruptMode); }
1. 刚开始 node 为空,就创建一个 node,状态为 Node.CONDITION
2. 释放锁,首先获取到状态 savedstate 肯定是>0 因为被加过锁,现在会走 tryRelease 释放锁,将线程占用设置为null,最后走 aqs 的 unparkSuccessor 方法获取等待队列中的第一个线程,去唤醒他。
3. 挂起自己,由于创建的时候自己状态是 CONDITION ,那就返回 false 通过 park(this) 把自己挂起来。
signal
。