最近面试被问到java concurrent包下有哪些熟悉的,用过的工具。所以来回顾一下,这些工具的底层实现,AbstractQueuedSynchronizer。在网上看到了其余人的一些技术博客,我将源码贴出,分享下本身不一样的看法。java
对于初看源码的我来讲,很奇怪,为何明明“waitThread1”已经拿到锁的状况下,而“singalThread”还能获取一样的锁而运行呢。这就得看源码才能分析明白。
一开始waitThread拿到了锁,而后调用了condition调用了await方法。
看看await方法:node
首先方法中会构建一个node用来表示该node如今在Condition的queue中。Condition的queue维护着一连串的node,当前线程被包含在其中。面试
接下来fullyRelease方法会将AQS的当前状态即state置为0(这里说的是具体的ReentrantLock的tryRelease实现方式,由于它是独占锁。)fullyRelease其中还会将AQS中维护的queue(其中一样是node,只是Condition中的node记录的是等待condition的node,AQS中的queue是等待锁的node)中的线程释放出来。注意,执行完这一步以后,若另外一个线程singalThread因为lock而得不到锁,已经在AQS的queue中,处于wait状态,这时他将被唤醒,而后获取到锁,从AQS的queue中删除。工具
当singalThread执行完singal的之中,就会将condition中的node移到AQS的queue上去。
具体代码在condition中的signal方法中:spa
将其node的状态改成SIGNAL,注意这个时候通常node尚未被唤醒。线程
一般上面这一句不会为true,除非没有能把目前node的状态改成SIGNAL,或者node state大于0了,这个时候说明任务呗取消了,那么以上两种状况都直接唤醒线程。除了上述两种状况外,由signalthread的unlock操做唤醒在AQS上的线程。队列
总的来讲,操做顺序是:ip
waitthread lock源码
Signalthread lock 进入AQS队列wait博客
waitthread await 唤醒 Signalthread,Signalthread成功得到锁
Signalthread signal 将waitthread 状态变为signal并将其从condition queue转到AQS queue
Signalthread unlock 使waitthread再次得到锁 执行余下代码。固然这是理由状态下,为了讨论AQS及condition的原理,实际的操做时序也有可能变化。