JDK 源码解析 —— Condition

一. 简介
使用 Condition 可以让线程等待不同条件,典型的例子就是 ArrayBlockingQueue。



二. 源码解析
Condition 接口的具体实现是在 AbstractQueuedSynchronized 类中一个叫做 ConditionObject 的内部类。

核心字段:
        /** condition 队列的第一个节点 */
        private transient Node firstWaiter;
        /** condition 队列的最后一个节点 */
        private transient Node lastWaiter;


  1. await() 方法:实现了可中断的条件等待
(1)如果当前线程中断,抛出中断异常
(2)保存锁状态通过 getStat 返回
(3)调用 release,参数是已保存的状态
(4)线程阻塞直到 signal 或者中断
(5)调用特定的 acquire 重新获取

(6)如果在(4)中断的话,抛出中断异常 

[java]  view plain  copy
  1. public final void await() throws InterruptedException {  
  2.     if (Thread.interrupted())  
  3.         throw new InterruptedException();  
  4.     Node node = addConditionWaiter(); // 当前线程加入等待队列,此时Node状态为等待状态  
  5.     int savedState = fullyRelease(node); // 释放当前线程占有的锁(await 是在 lock 后才能调用)  
  6.     int interruptMode = 0;  
  7.     while (!isOnSyncQueue(node)) {   // 不在AQS的同步等待队列里,说明还没达到获取锁的条件,这时线程还在Condition的队列里,得//signal了才能进入AQS同步队列。所以现在只能卡在这  
  8.         LockSupport.park(this);  
  9.         if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)// 如果线程中断,则退出死循环  
  10.             break;  
  11.     }  
  12.     if (acquireQueued(node, savedState) && interruptMode != THROW_IE) // 因为上述线程释放锁,所以AQS等待队列节点可以获取锁  
  13.         interruptMode = REINTERRUPT;  
  14.     if (node.nextWaiter != null// clean up if cancelled  
  15.         unlinkCancelledWaiters();  
  16.     if (interruptMode != 0)  
  17.         reportInterruptAfterWait(interruptMode);  
  18. }  


2. signal() 方法:

[java]  view plain  copy
  1. public final void signal() {  
  2.     if (!isHeldExclusively())  
  3.         throw new IllegalMonitorStateException();  
  4.     Node first = firstWaiter;  
  5.     if (first != null)  
  6.         doSignal(first);  
  7. }  
  8.   
  9. private void doSignal(Node first) {  
  10.     do {  
  11.         if ( (firstWaiter = first.nextWaiter) == null)  
  12.             lastWaiter = null;  
  13.         first.nextWaiter = null;  
  14. // 将节点从 Condition 队列移动到 AQS 的同步队列,移出一个节点循环就会结束  
  15.     } while (!transferForSignal(first) &&  
  16.              (first = firstWaiter) != null);  
  17. }  


3.  signalAll() 方法:

[java]  view plain  copy
  1. public final void signalAll() {  
  2.     if (!isHeldExclusively())  
  3.         throw new IllegalMonitorStateException();  
  4.     Node first = firstWaiter;  
  5.     if (first != null)  
  6.         doSignalAll(first);  
  7. }  
  8. private void doSignalAll(Node first) {  
  9.     lastWaiter = firstWaiter = null;  
  10.     do {  
  11.         Node next = first.nextWaiter;  
  12.         first.nextWaiter = null;  
  13.         transferForSignal(first);  
  14.         first = next;  
  15.     } while (first != null);// 全部移出 Condition 等待队列  
  16. }  



转载自:https://blog.csdn.net/wenniuwuren/article/details/51447767

猜你喜欢

转载自blog.csdn.net/jr_way/article/details/80173854