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();
    }
View Code

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

已经写烂了,不想再写了 (传送门走起)。

原文地址:https://www.cnblogs.com/wlwl/p/15039814.html