<div id="navCategory"></div>
讯享网
想必大家都使用过wait()和notify()这两个方法把,这两个方法主要用于多线程间的协同处理,即控制线程之间的等待、通知、切换及唤醒。而RenentrantLock也支持这样条件变量的能力,而且相对于synchronized 更加强大,能够支持多个条件变量。
最好可以先阅读ReentrantLock系列文章:
图解Java ReentrantLock公平锁和非公平锁的实现
详解Java ReentrantLock可重入,可打断,锁超时的实现原理
ReentrantLock类API
: 创建条件变量对象
Condition类API
- : 当前线程从运行状态进入等待状态,同时释放锁,该方法可以被中断
- :当前线程从运行状态进入等待状态,该方法不能够被中断
- : 唤醒一个等待在 Condition 条件队列上的线程
- : 唤醒阻塞在条件队列上的所有线程
运行结果:
- condition的wait和notify必须在lock范围内
- 实现条件变量的等待和唤醒,他们必须是同一个condition。
- 线程1执行conidtion.notify()后,并没有释放锁,需要等释放锁后,线程0重新获取锁成功后,才能继续向下执行。
1.线程0(Thread-0)一开始获取锁,exclusiveOwnerThread字段是Thread-0, 如下图中的深蓝色节点

2.Thread-0调用await方法,Thread-0封装成Node进入ConditionObject的队列,因为此时只有一个节点,所有firstWaiter和lastWaiter都指向Thread-0,会释放锁资源,NofairSync中的state会变成0,同时exclusiveOwnerThread设置为null。如下图所示。

3.线程1(Thread-1)被唤醒,重新获取锁,如下图的深蓝色节点所示。

4.Thread-0被park阻塞,如下图灰色节点所示:


源码如下:
下面是await()方法的整体流程,其中进行阻塞当前线程,后续唤醒,也会在这个程序点恢复执行。
将线程封装成Node, 加入到ConditionObject队列尾部,此时节点的等待状态时-2。
清理条件队列中的cancel类型的节点,比如中断、超时等会导致节点转换为Cancel
fullyRelease方法将r让Thread-0释放锁, 这个时候Thread-1就会去竞争锁
判断节点是否在AQS阻塞对列中,不在条件对列中
1.Thread-1执行signal方法唤醒条件队列中的第一个节点,即Thread-0,条件队列置空

2.Thread-0的节点的等待状态变更为0, 重新加入到AQS队列尾部。

3.后续就是Thread-1释放锁,其他线程重新抢锁。
源码如下:
signal()方法是唤醒的入口方法
调用doSignal()方法唤醒节点
调用transferForSignal()方法,先将节点的 waitStatus 改为 0,然后加入 AQS 阻塞队列尾部,将 Thread-3 的 waitStatus 改为 -1。
以上就是图解Java ReentrantLock的条件变量Condition机制的详细内容,更多关于ReentrantLock条件变量Condition机制的资料请关注脚本之家其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/207854.html