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

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

posted @   吴磊的  阅读(159)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
//生成目录索引列表
点击右上角即可分享
微信分享提示