Condition初解

Condition初解

public interface Lock {
	//返回绑定到此Lock实例的新Condition实例。 用于实现线程间的通信
    //类似于 synchronized 调用 Object的wait()和notify()/notifyAll() 方法
  	Condition newCondition();
}
//Condition接口
public interface Condition {

    /**
     * 使当前线程等待,直到发出信号或 中断。
     * 与此 Condition 相关的锁以原子方式释放,当前线程因线程调度目的而被禁用并处于休眠状态,直到发生以下四种情况 之一 :
     *   其他一些线程为此Condition调用了该signal方法,而当前线程恰好被选为要唤醒的线程;
     *   其他一些线程为此Condition调用该signalAll方法;
     *   其他一些线程会中断当前线程,并且支持线程挂起的中断 ;
     *   发生“虚假唤醒”。
     * 在所有情况下,在此方法返回之前,当前线程必须重新获取与此条件关联的锁。当线程返回时,它 保证 保持此锁。
     *   如果当前线程:
     *   在进入此方法时设置了中断状态;或
     *   在等待时被中断,并支持线程挂起的 中断 ,
     *   然后 InterruptedException 被抛出,当前线程的中断状态被清除。在第一种情况下,没有指定是否在释放锁之前进行中断测试。	
     */
    void await() throws InterruptedException;

    /**
     * 使当前线程等待,直到发出信号。
     * 根据上一个方法相比较、不支持中断	
     */
    void awaitUninterruptibly();

    /**
     * 使当前线程等待,直到发出信号或中断,或者经过指定的等待时间。
     */
    long awaitNanos(long nanosTimeout) throws InterruptedException;

    /**
     * 使当前线程等待,直到发出信号或中断,或者经过指定的等待时间。此方法在行为上等效于:
 	 *	awaitNanos(unit.toNanos(time)) > 0      
     */
    boolean await(long time, TimeUnit unit) throws InterruptedException;

    /**
     * 使当前线程等待,直到发出信号或中断,或者指定的截止时间过去。
     */
    boolean awaitUntil(Date deadline) throws InterruptedException;

    /**
     *	唤醒一个等待线程。
	 *	如果有任何线程正在等待此条件,则选择一个线程进行唤醒。然后,该线程必须重新获取锁,然后才能从 await返回。
	 *	注意事项
	 *	可能(并且通常确实)要求当前线程在调用此方法时持有与此 Condition 关联的锁。实现必须记录此前提条件以及未保持锁时采取的任何操作。通常, 			 *	IllegalMonitorStateException 将引发异常。
     */
    void signal();

    /**
     *	唤醒所有等待线程。
	 *	如果有任何线程正在等待这种情况,则它们都将被唤醒。每个线程必须先重新获取锁,然后才能从 await返回。
	 *	注意事项
	 *	可能(并且通常确实)要求当前线程在调用此方法时持有与此 Condition 关联的锁。实现必须记录此前提条件以及未保持锁时采取的任何操作。通常, 			 *	IllegalMonitorStateException 将引发异常。
     */
    void signalAll();
}

AQS中Condition的实现

    public class ConditionObject implements Condition, java.io.Serializable {
        private static final long serialVersionUID = 1173984872572414699L;
        /** First node of condition queue. */
        private transient Node firstWaiter;
        /** Last node of condition queue. */
        private transient Node lastWaiter;

        /**
         * Creates a new {@code ConditionObject} instance.
         */
        public ConditionObject() { }
    }

AQS中的ConditionObject实现了Condition接口,ConditionObject维护了一个NODE的单向链表,NODE使用的是AQS中定义的NODE节点,NODE的默认状态为Node.CONDITION(-2)

通过ReentrantLock解析AQS实现Condition的具体细节

    //实现了lock接口的方法
	public Condition newCondition() {
        return sync.newCondition();
    }
    final ConditionObject newCondition() {
        //返回一个ConditionObject示例
        return new ConditionObject();
    }

ConditionObject.await() throws InterruptedException

	 public final void await() throws InterruptedException {
         	//判断当前线程是否是中断状态
            if (Thread.interrupted())
                throw new InterruptedException();
         	//向ConditionObject维护的单向链表中增加一个节点
            Node node = addConditionWaiter();
         	//在调用此方法时当前线程持有锁,释放当前线程持有的所有锁
            int savedState = fullyRelease(node);
            int interruptMode = 0;
         	//自旋 如果当前节点不在等待的同步队列中 
            while (!isOnSyncQueue(node)) {
                //挂起当前线程 如果当前线程设置了中断标识 则会直接唤醒 sleep join wait 方法设置了中断则会直接抛出异常
                //设置了中断的线程不会被挂起
                LockSupport.park(this);
                //检查该线程的中断时机(判断是中断唤醒了线程还是signal唤醒的当前线程) 返回中断模式 
                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);
        }
		//向ConditionObject维护的双向链表中增加一个节点 ConditionObject方法
        private Node addConditionWaiter() {
            //最后一个等待节点
            Node t = lastWaiter;
            // If lastWaiter is cancelled, clean out.
            if (t != null && t.waitStatus != Node.CONDITION) {
                //如果最后一个节点不是条件等待状态,移除队列中的所有取消状态节点
                unlinkCancelledWaiters();
                t = lastWaiter;
            }
            //创建一个新节点 线程信息为当前线程 状态为等待状态-2
            Node node = new Node(Thread.currentThread(), Node.CONDITION);
            //并将该节点放在队列的末尾
            if (t == null)
                firstWaiter = node;
            else
                t.nextWaiter = node;
            lastWaiter = node;
            //返回当前节点
            return node;
        }
		//断开所有取消状态的等待者 ConditionObject方法
        private void unlinkCancelledWaiters() {
            //第一个节点
            Node t = firstWaiter;
            Node trail = null;
            while (t != null) {
                Node next = t.nextWaiter;
                if (t.waitStatus != Node.CONDITION) {
                    t.nextWaiter = null;
                    if (trail == null)
                        firstWaiter = next;
                    else
                        trail.nextWaiter = next;
                    if (next == null)
                        lastWaiter = trail;
                }
                else
                    trail = t;
                t = next;
            }
        }
		//释放当前线程持有的所有锁 会唤起位于head下一个等待的线程节点 AQS方法
        final int fullyRelease(Node node) {
            boolean failed = true;
            try {
                //获取状态如果重入了锁状态大于1
                int savedState = getState();
                //释放锁
                if (release(savedState)) {
                    failed = false;
                    return savedState;
                } else {
                    throw new IllegalMonitorStateException();
                }
            } finally {
                if (failed)
                    //释放锁失败,当前节点状态改为取消
                    node.waitStatus = Node.CANCELLED;
            }
        }
		//如果最初放置在条件队列上的节点(始终是节点)现在正在等待在同步队列上重新获取,则返回 true。 AQS方法
		//判断当前节点是否在需要排队的同步队列中
        final boolean isOnSyncQueue(Node node) {
            //如果节点状态为条件等待 或者prev == null 则不在队列中
            if (node.waitStatus == Node.CONDITION || node.prev == null)
                return false;
            //如果有下一节点表明在队列中
            if (node.next != null) // If has successor, it must be on queue
                return true;
            /*
             * node.prev can be non-null, but not yet on queue because
             * the CAS to place it on queue can fail. So we have to
             * traverse from tail to make sure it actually made it.  It
             * will always be near the tail in calls to this method, and
             * unless the CAS failed (which is unlikely), it will be
             * there, so we hardly ever traverse much.
             */
            //在队列中从尾部去查当前节点
            return findNodeFromTail(node);
        }
		//如果节点通过从尾部向后搜索在同步队列上,则返回 true。仅当 isOnSyncQueue 需要时才调用。
        private boolean findNodeFromTail(Node node) {
            Node t = tail;
            for (;;) {
                if (t == node)
                    return true;
                if (t == null)
                    return false;
                t = t.prev;
            }
        }
		//检查中断,如果在发出信号之前中断,则返回 THROW_IE,如果在发出信号后返回 REINTERRUPT,如果未中断,则返回 0。
        private int checkInterruptWhileWaiting(Node node) {
            return Thread.interrupted() ?
                //发出信号之前中断了 则返回中断抛出异常模式
                (transferAfterCancelledWait(node) ? THROW_IE : REINTERRUPT) : 0;
        }
		//如有必要,传输节点以在取消等待后同步队列。如果线程在发出信号之前被取消,则返回 true。
		//取消等待后转移
        final boolean transferAfterCancelledWait(Node node) {
            //如果节点的状态从条件等待改为了默认 将该节点加入到同步队列尾部,如果获取到锁则执行
            //signal 方法唤醒线程会设置当前线程的ws为0 如果此方法成功则说明 当前线程在发出信号之前中断了
            if (compareAndSetWaitStatus(node, Node.CONDITION, 0)) {
                enq(node);
                return true;
            }
            /*
             * If we lost out to a signal(), then we can't proceed
             * until it finishes its enq().  Cancelling during an
             * incomplete transfer is both rare and transient, so just
             * spin.
             */
            //如果唤醒之后中断了 如果此线程没在同步队列中 这放弃当前cpu 直到被放到同步队列中
            while (!isOnSyncQueue(node))
                Thread.yield();
            return false;
        }
		//引发 InterruptedException、重新中断当前线程或不执行任何操作,具体取决于模式
        private void reportInterruptAfterWait(int interruptMode)
            throws InterruptedException {
            if (interruptMode == THROW_IE)
                throw new InterruptedException();
            else if (interruptMode == REINTERRUPT)
                selfInterrupt();
        }

ConditionObject.awaitUninterruptibly()

    //使一个线程等待不会响应中断
	public final void awaitUninterruptibly() {
            //将当前线程节点添加到条件等待队列中
            Node node = addConditionWaiter();
        	//释放锁
            int savedState = fullyRelease(node);
            boolean interrupted = false;
            while (!isOnSyncQueue(node)) {
                LockSupport.park(this);
                //如果被中断标识唤醒(清除中断标识)防止在重新获取锁的过程中无法挂起当前线程 则记录中断标识
                if (Thread.interrupted())
                    interrupted = true;
            }
        	//如果中断了则标识当前线程为中断状态
            if (acquireQueued(node, savedState) || interrupted)
                selfInterrupt();
        }

ConditionObject.awaitNanos(long nanosTimeout) throws InterruptedException

实现定时条件等待。
1如果当前线程中断,则抛出 InterruptedException。
2保存 返回的 getState锁定状态。
3使用保存的状态作为参数进行调用 release ,如果失败,则抛出 IllegalMonitorStateException。
4阻塞,直到发出信号、中断或超时。
5通过调用 with saved state 作为参数的 acquire 专用版本来重新获取。
6如果在步骤 4 中被阻止时中断,则引发 InterruptedException。

        public final long awaitNanos(long nanosTimeout)
                throws InterruptedException {
            if (Thread.interrupted())
                throw new InterruptedException();
            Node node = addConditionWaiter();
            int savedState = fullyRelease(node);
            //计算等待超时时间点
            final long deadline = System.nanoTime() + nanosTimeout;
            int interruptMode = 0;
            while (!isOnSyncQueue(node)) {
                //等待时间为负数 表示等待已经超时 尝试将节点加入到同步队列 或者被signal通知加入到同步队列
                if (nanosTimeout <= 0L) {
                    transferAfterCancelledWait(node);
                    break;
                }
                //根据spinForTimeoutThreshold判断是需要挂起还是自旋
                if (nanosTimeout >= spinForTimeoutThreshold)
                    LockSupport.parkNanos(this, nanosTimeout);
                if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                    break;
                //重新赋值剩余等待时间
                nanosTimeout = deadline - System.nanoTime();
            }
            //在同步队列中尝试获取锁 启动该线程
            if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                interruptMode = REINTERRUPT;
            if (node.nextWaiter != null)
                unlinkCancelledWaiters();
            if (interruptMode != 0)
                reportInterruptAfterWait(interruptMode);
            //该值的 nanosTimeout 估计值减去从此方法返回后等待所花费的时间。正值可以用作后续调用此方法的参数,以完成等待所需				时间。小于或等于零的值表示没有剩余时间
            return deadline - System.nanoTime();
        }

ConditionObject.await(long time, TimeUnit unit) throws InterruptedException

实现定时条件等待。
1如果当前线程中断,则抛出 InterruptedException。
2保存 返回的 getState锁定状态。
3使用保存的状态作为参数进行调用 release ,如果失败,则抛出 IllegalMonitorStateException。
4阻塞,直到发出信号、中断或超时。
5通过调用 with saved state 作为参数的 acquire 专用版本来重新获取。
6如果在步骤 4 中被阻止时中断,则引发 InterruptedException。
7如果在步骤 4 中被阻止时超时,则返回 false,否则为 true。

        public final boolean await(long time, TimeUnit unit)
                throws InterruptedException {
            long nanosTimeout = unit.toNanos(time);
            if (Thread.interrupted())
                throw new InterruptedException();
            Node node = addConditionWaiter();
            int savedState = fullyRelease(node);
            final long deadline = System.nanoTime() + nanosTimeout;
            boolean timedout = false;
            int interruptMode = 0;
            while (!isOnSyncQueue(node)) {
                if (nanosTimeout <= 0L) {
                    timedout = transferAfterCancelledWait(node);
                    break;
                }
                if (nanosTimeout >= spinForTimeoutThreshold)
                    LockSupport.parkNanos(this, nanosTimeout);
                if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                    break;
                nanosTimeout = deadline - System.nanoTime();
            }
            if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                interruptMode = REINTERRUPT;
            if (node.nextWaiter != null)
                unlinkCancelledWaiters();
            if (interruptMode != 0)
                reportInterruptAfterWait(interruptMode);
            return !timedout;
        }

ConditionObject.awaitUntil(Date deadline) throws InterruptedException

实现绝对定时条件等待。
1如果当前线程中断,则抛出 InterruptedException。
2保存 返回的 getState锁定状态。
3使用保存的状态作为参数进行调用 release ,如果失败,则抛出 IllegalMonitorStateException。
4阻塞,直到发出信号、中断或超时。
5通过调用 with saved state 作为参数的 acquire 专用版本来重新获取。
6如果在步骤 4 中被阻止时中断,则引发 InterruptedException。
7如果在步骤 4 中被阻止时超时,则返回 false,否则为 true。

        public final boolean awaitUntil(Date deadline)
                throws InterruptedException {
            long abstime = deadline.getTime();
            if (Thread.interrupted())
                throw new InterruptedException();
            Node node = addConditionWaiter();
            int savedState = fullyRelease(node);
            boolean timedout = false;
            int interruptMode = 0;
            while (!isOnSyncQueue(node)) {
                if (System.currentTimeMillis() > abstime) {
                    timedout = transferAfterCancelledWait(node);
                    break;
                }
                LockSupport.parkUntil(this, abstime);
                if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                    break;
            }
            if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                interruptMode = REINTERRUPT;
            if (node.nextWaiter != null)
                unlinkCancelledWaiters();
            if (interruptMode != 0)
                reportInterruptAfterWait(interruptMode);
            return !timedout;
        }

ConditionObject.signal()

    //唤醒该条件下的一个线程   	
    public final void signal() {
        //判断执行通知的线程是不是当前持有锁的线程
        if (!isHeldExclusively())
            throw new IllegalMonitorStateException();
        //条件等待队列中的第一个等待者
        Node first = firstWaiter;
        if (first != null)
            //执行通知
            doSignal(first);
    }
	//如果以独占方式保持同步则为true 否则为false ReentrantLock的sync重写了AQS的方法
	//默认实现抛出 UnsupportedOperationException.此方法仅在方法内部 AbstractQueuedSynchronizer.ConditionObject 调		用,因此,如果不使用条件,则无需定义此方法。
    protected final boolean isHeldExclusively() {
        // While we must in general read state before owner,
        // we don't need to do so to check if current thread is owner
        return getExclusiveOwnerThread() == Thread.currentThread();
    }
	//
    private void doSignal(Node first) {
        do {
            if ( (firstWaiter = first.nextWaiter) == null)
                lastWaiter = null;
            first.nextWaiter = null;
             //如果将first放入同步队列失败 并且还有下一个条件节点则唤醒下一个
        } while (!transferForSignal(first) &&
                 (first = firstWaiter) != null);
    }
	//将节点从条件队列传输到同步队列。如果成功,则返回 true。
    final boolean transferForSignal(Node node) {
        /*
         * If cannot change waitStatus, the node has been cancelled.
         */
        //如果没有赋值成功表示此node节点线程被中断唤醒已经是处于取消状态
        if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
            return false;

		//拼接到队列并尝试设置 Predecessor 的 waitStatus 以指示线程(可能)正在等待。如果取消或尝试设置 waitStatus 失败,			请唤醒以重新同步(在这种情况下,waitStatus 可能是暂时且无害的错误)。
        //将此条件节点放到同步节点尾部 返回的是node的前一节点
        Node p = enq(node);
        int ws = p.waitStatus;
        //如果前一节点处于取消状态 或者SIGNAL状态没有赋值成功则直接唤醒该节点线程
        //如果前一线程为Node.SIGNAL则等待前一线程 唤醒此线程
        if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
            LockSupport.unpark(node.thread);
        return true;
    }

ConditionObject.signalAll()

    //唤醒所有等待线程 
    public final void signalAll() {
        if (!isHeldExclusively())
            throw new IllegalMonitorStateException();
        Node first = firstWaiter;
        if (first != null)
            doSignalAll(first);
    }
    private void doSignalAll(Node first) {
        //将条件队列 清空
        lastWaiter = firstWaiter = null;
        do {
            Node next = first.nextWaiter;
            first.nextWaiter = null;
            //循环将所有的条件节点同步到同步队列中
            transferForSignal(first);
            first = next;
        } while (first != null);
    }
  • 19
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值