• Condition源码解析


    可以通过ReentrantLock.newCondition()来获得Condition对象

    public Condition newCondition() {
            return sync.newCondition(); //实际上是调用AQS的方法
        }
    final ConditionObject newCondition() {
                return new ConditionObject(); //ConditionObject实现了Condition方法
            }

    Condition的await()方法

    public final void await() throws InterruptedException {
                if (Thread.interrupted())
                    throw new InterruptedException();
                Node node = addConditionWaiter(); //添加到等待队列里
                int savedState = fullyRelease(node); //释放锁并唤醒线程
                int interruptMode = 0;
                while (!isOnSyncQueue(node)) {
                    LockSupport.park(this); 
                    if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                        break;
                }
                if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                    interruptMode = REINTERRUPT;
                if (node.nextWaiter != null) // clean up if cancelled
                    unlinkCancelledWaiters();
                if (interruptMode != 0)
                    reportInterruptAfterWait(interruptMode);
            }
     private Node addConditionWaiter() {
                Node t = lastWaiter;
                // If lastWaiter is cancelled, clean out.
                if (t != null && t.waitStatus != Node.CONDITION) {
                    unlinkCancelledWaiters();
                    t = lastWaiter;
                }
                Node node = new Node(Thread.currentThread(), Node.CONDITION); //新建一个Node对象,WaitStatus属性设置为CONDITION
                if (t == null)
                    firstWaiter = node;        //设为首节点
                else 
                    t.nextWaiter = node;      //添加到链表尾
                lastWaiter = node;
                return node;
            }
     final int fullyRelease(Node node) {
            boolean failed = true;
            try {
                int savedState = getState();
                if (release(savedState)) {   //释放锁,并唤醒队列里的第一个线程
                    failed = false;
                    return savedState;
                } else {
                    throw new IllegalMonitorStateException();
                }
            } finally {
                if (failed)
                    node.waitStatus = Node.CANCELLED;
            }
        }

    singal()方法

     public final void signal() {
                if (!isHeldExclusively())
                    throw new IllegalMonitorStateException();
                Node first = firstWaiter;
                if (first != null)
                    doSignal(first); //doSignal主要就是把等待队列的第一个节点移动同步队列的尾节点中去
            }
     private void doSignal(Node first) {
                do {
                    if ( (firstWaiter = first.nextWaiter) == null)//把下一个节点设为首节点,如果首节点的下一个节点为空,说明队列只有一个节点,
                        lastWaiter = null;         //把尾节点置为null;
                    first.nextWaiter = null;       //把首节点从队列中清除
                } while (!transferForSignal(first) &&
                         (first = firstWaiter) != null);
            }
    final boolean transferForSignal(Node node) {
            /*
             * If cannot change waitStatus, the node has been cancelled.
             */
            if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))  //把节点的waitStatuss设为CONDITION
                return false;
    
            /*
             * Splice onto queue and try to set waitStatus of predecessor to
             * indicate that thread is (probably) waiting. If cancelled or
             * attempt to set waitStatus fails, wake up to resync (in which
             * case the waitStatus can be transiently and harmlessly wrong).
             */
            Node p = enq(node);  //把节点添加到同步队列的尾部
            int ws = p.waitStatus;
            if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))  //通过cas把节点的waitStatus设为SIGNAL
                LockSupport.unpark(node.thread);
            return true;
        }

    所以Condition的await方法和singal方法的作用:

    await就是把当前获得锁的线程添加到等待队列中,并阻塞队列,同时释放锁并唤醒同步队列中的线程

    singal就是把等待队列的头结点添加到同步队列中的尾部,等待唤醒.

    public final void await() throws InterruptedException {
    if (Thread.interrupted())
    throw new InterruptedException();
    Node node = addConditionWaiter();
    int savedState = fullyRelease(node);
    int interruptMode = 0;
    while (!isOnSyncQueue(node)) {
    LockSupport.park(this);
    if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
    break;
    }
    if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
    interruptMode = REINTERRUPT;
    if (node.nextWaiter != null) // clean up if cancelled
    unlinkCancelledWaiters();
    if (interruptMode != 0)
    reportInterruptAfterWait(interruptMode);
    }
  • 相关阅读:
    开发者使用JasperReport——通过数据源生成报表
    《编程导论(Java)》电子参考文献索引
    QT信号的自定义
    uCOS3空闲任务
    php函数nl2br的反函数br2nl
    PHPstorm相关设置以及快捷键
    phpstorm 左边的文件列表没用了 怎么弄出来
    nl2br()与nl2p()函数,php在字符串中的新行(\n)之前插入换行符
    DNS配置&HTTP 规格严格
    GC与幽灵引用 规格严格
  • 原文地址:https://www.cnblogs.com/lzh66/p/13230371.html
Copyright © 2020-2023  润新知