• 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

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

  • 相关阅读:
    rand()和srand()
    advanced regression to predict housing prices
    数学建模
    python的对数
    八月总结——人工智能初学者
    看到的不错的项目
    学习笔记(七): Logistic Regression
    学习笔记(六): Regularization for Simplicity
    An Intuitive Explanation of Convolutional Neural Networks
    CentOS7的mysql5.7-rpm.bundle方式安装
  • 原文地址:https://www.cnblogs.com/wlwl/p/15039814.html
Copyright © 2020-2023  润新知