脚本宝典收集整理的这篇文章主要介绍了读源码笔记 Java AbstractQueuedSynchronizer,脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
AQS Condition
最近面试被问到java concurrent包下有哪些熟悉的,用过的工具。因此来回顾一下,这些工具的底层实现,AbstractQueuedSynchronizer。在网上看到了其他人的一些技术博客,我将源码贴出,分享下自己不同的见解。
分析源码
对于初看源码的我来说,很奇怪,为什么明明“waitThread1”已经拿到锁的情况下,而“singalThread”还能获取同样的锁而运行呢。这就得看源码才能分析明白。
一开始waitThread拿到了锁,然后调用了condition调用了await方法。
看看await方法:
首先方法中会构建一个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方法中:
将其node的状态改为SIGNAL,注意这个时候一般node还没有被唤醒。
通常上面这一句不会为true,除非没有能把目前node的状态改为SIGNAL,或者node state大于0了,这个时候说明任务呗取消了,那么以上两种情况都直接唤醒线程。除了上述两种情况外,由signalthread的unlock操作唤醒在AQS上的线程。
总结
总的来说,操作顺序是:
waitthread lock
Signalthread lock 进入AQS队列wait
waitthread await 唤醒 Signalthread,Signalthread成功获得锁
Signalthread signal 将waitthread 状态变为signal并将其从condition queue转到AQS queue
Signalthread unlock 使waitthread再次获得锁 执行余下代码。
当然这是理由状态下,为了讨论AQS及condition的原理,实际的操作时序也有可能变化。
以上是脚本宝典为你收集整理的读源码笔记 Java AbstractQueuedSynchronizer全部内容,希望文章能够帮你解决读源码笔记 Java AbstractQueuedSynchronizer所遇到的问题。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。