您的位置:首页 > 博客中心 > 数据库 >

[源码]Condition的原理,简单案例(ArrayBlockingQueue),复杂案例(LinkedBlockingQueue).

时间:2022-03-10 17:46

  源代码解析 Re‘entrantLock lock = new ReentrantLock(fair);   Condition   notEmpty = lock.newCondition(); //返回内部类 AbstractQueuedSyncronizer.ConditionObject    各自维护了两个队列.一个是阻塞同步队列 syncQueue 双向队列,一个是条件等待队列.    Condition.await两个作用.1.放入同步队列 park 2.realse锁,3等待别人获取锁acquire(),并且.signal .unlock()之后调用acquiredQueue()从阻塞同步队列里复活出来.    Condition..signal 1.在父类Locker.lock()获取锁之后,从条件队列迁移到阻塞同步队列.2.等待之后的unlcok 释放锁,并唤醒next线程. 能够park .signal 完成线程加入到阻塞队列中( 因为signal必须在对应的lock()后操作. 所以从条件队列中迁移出不可能获得锁,只能加入到线程队列中.)   之前的误区: 何时await的线程被唤醒?和正在syncQueue中的线程优先级哪个高?    我理解为signal之后唤醒await线程.    正确理解: signal只是转移线程,并不是唤醒await队列的地方.真正唤醒await线程的地方在持有Locker.unlock的时候.(见LinkedBlockingQueue中的signalNotFull()方法.) await线程被转移到syncQueue时,已经有线程在排队,那么只好放在队尾.   下面有LinkedBlockingQueue的先take,await, 然后被put.signal的时序图.
  private void signalNotEmpty() {         final ReentrantLock takeLock = this.takeLock;         takeLock.lock();         try {             notEmpty.signal(); // phil:必须在lock()后面,锁已经被线程获取了.         } finally {             takeLock.unlock();         }     }    ReentrantLock.unlock完成下一个线程(可能刚好是signal加入的)的unpark.
所以总结: signal后不一定是之前的那个await的线程.  获得锁执行..



gxlsystem.com,布布扣

[源码]Condition的原理,简单案例(ArrayBlockingQueue),复杂案例(LinkedBlockingQueue).,布布扣,bubuko.com

热门排行

今日推荐

热门手游