在《基于线程、并发的基本概念(详解)》中,我们利用synchronized关键字、Queue队列、以及Object监视器方法实现了生产者消费者,介绍了有关线程的一些基本概念。Object类提供的wait的方法和notifyAll方法,与之对应的是Condition接口提供是await和signalAll。await(或wait)是让当前线程进入等待状态并释放锁,signalAll(或notifyAll)则是唤醒等待中的线程,使得等待中的线程有竞争锁的资格,注意只是资格,并不代表被唤醒的线程就一定会获得锁。

Condition接口的具体实现还是在AbstractQueuedSynchronizer中的内部实现的——AbstractQueuedSynchronizer$ConditionObject。ConditionObject中维护了一个“等待队列”,注意这个和AQS同步器维护的“同步队列”不同。AQS所维护的同步队列是当前等待资源(同步状态)的队列,当前线程获取同步状态失败时,同步器会将当前线程以及等待状态等信息构造成一个节点并加入到同步队列中,同时阻塞当前线程,当同步状态被所持有的线程释放时会将同步队列中的首节点唤醒重新获取同步状态。而每个Condition维护一个等待队列,该队列的作用是一个等待signal信号的队列。这两者之间的关系是一个协同的关系,用下图的说明它们之间的协同过程:
1. AQS的同步队列如下图所示,一个头结点head指向队首,一个tail指向队尾,当线程调用lock()方法获取锁而未成功时,线程被构造成节点加入到队尾。(图中NodeA是同步队列的第一个节点,也就是获得同步状态的节点)
2.NodeA调用await()方法时,NodeA从AQS同步队列中移除,自然也就释放了锁,NodeA此时被加入到Condition的等待队列中,等待signal信号,如下图所示。
3.执行完第2步后,此时NodeB在同步队列中处于第一个节点位置,即获取到了锁,如果NodeB此时执行signal(或者signalAll)方法,NodeA将会从Condition等待队列中被移除即被唤醒,加入到同步队列中,此时NodeA仅仅是被唤醒有了在同步队列中争夺资源的资格,并不代表被唤醒后就立即获得锁,如下图所示。
4. 最后NodeB在signal执行完毕后,调用unLock方法释放锁,此时NodeA处于队首,并争夺同步状态。
以上是AQS的“同步队列”和Condition的“等待队列”之间相互协作的过程,下面从源码解析Condition的主要方法await、signal、signalAll。
public final void await() throws InterruptedException{
if (Thread.interrupted()) //线程被中断则抛出中断异常
throw new InterruptedException();
Node node = addConditionWaiter(); //将线程构造为Node节点
long savedState = fullyRelease(node); //释放锁,返回同步状态
int interruptMode = 0;
while (!isOnSyncQueue(node)) { //循环判断当前节点是否在同步队列中
LockSupport.park(this);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break; //检查节点在处于等待状态时是否被中断
}
//在跳出了循环,即被signal唤醒后重新加入了同步队列后,开始重新竞争锁
if (acquireQueued(node, savedState) && interruptMode != THROW_IE) //acquireQueued自旋获取锁,具体分析见《2.从AbstractQueuedSynchronizer(AQS)说起(1)——独占模式的锁获取与释放》中对获取同步状态的解析
interruptMode = REINTERRUPT;
if (node.nextWaiter != null)
unlinkCancelledWaiters(); //如果节点从等待状态转换为在同步队列中,并且也已经获得了锁,此时将断开此节点后面的等待节点
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
}
在获取锁的线程调用await时,首先会将线程构造为Node节点并释放锁,此时线程被移出同步队列加入到Condition等待队列中,接着在第7行就会while循环判断节点是否在同步队列中,当没有线程调用signal方法的时候显然线程不在同步队列,并将一直循环,直到有线程调用signal方法该线程才会被唤醒加入到同步队列中,此时才会跳出循环。
signal和signalAll方法的异同在和notify和notifyAll一样。signal只会唤醒等待队列中位于队首的节点使其具有竞争锁的资格,而signalAll则会唤醒等待队列中所有节点使所有节点都具有竞争锁的资格。
public final void signal() {
if (!isHeldExclusively()) //判断当前线程是否持有锁
throw new IllegalMonitorStateException();
Node first = firstWaiter;
if (first != null)
doSignal(first); //唤醒等待队列中的第一个节点
}
对比signalAll方法,不同点在于第6行是唤醒等待队列中的所有节点——doSignalAll(first),不再贴出代码。
private void doSignal(Node first) {
do {
if ((firstWaiter = first.nextWaiter) == null)
lastWaiter = null;
first.nextWaiter = null;
} while (!transferForSignal(first) && (first = firstWaiter) != null) //transferForSignal方法将处于等待队列中的节点添加到同步队列中
}
至于doSignalAll则是循环调用transferForSignal使得所有节点都被唤醒加入到同步队列中。
当节点从等待队列中加入到同步队列中时,呼应await中的循环等待节点是否在同步队列中,await和signal的协同配合也就很清晰明了了。
以上这篇类似Object监视器方法的Condition接口(详解)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。
# Condition接口
# Java多线程编程中使用Condition类操作锁的方法详解
# 第一个
# 所示
# 是一个
# 如下图
# 也就
# 则是
# 才会
# 给大家
# 并不代表
# 会将
# 基本概念
# 移除
# 的是
# 就会
# 是在
# 将会
# 只会
# 希望能
# 并将
# 仅仅是
相关文章:
,购物网站怎么盈利呢?
建站VPS配置与SEO优化指南:关键词排名提升策略
如何在云服务器上快速搭建个人网站?
长沙做网站要多少钱,长沙国安网络怎么样?
建站之星如何快速生成多端适配网站?
如何通过wdcp面板快速创建网站?
临沂网站制作公司有哪些,临沂第四中学官网?
企业微网站怎么做,公司网站和公众号有什么区别?
如何快速搭建二级域名独立网站?
南宁网站建设制作定制,南宁网站建设可以定制吗?
合肥做个网站多少钱,合肥本地有没有比较靠谱的交友平台?
建站之星后台管理:高效配置与模板优化提升用户体验
香港服务器网站卡顿?如何解决网络延迟与负载问题?
如何通过VPS建站实现广告与增值服务盈利?
在线制作视频的网站有哪些,电脑如何制作视频短片?
音响网站制作视频教程,隆霸音响官方网站?
建站主机选购指南:核心配置优化与品牌推荐方案
广州商城建站系统开发成本与周期如何控制?
Python路径拼接规范_跨平台处理说明【指导】
制作网站的模板软件,网站怎么建设?
公司门户网站制作流程,华为官网怎么做?
如何用已有域名快速搭建网站?
网站专业制作公司,网站编辑是做什么的?好做吗?工作前景如何?
制作网站的网址是什么,请问后缀为.com和.com.cn还有.cn的这三种网站是分别是什么类型的网站?
在线制作视频网站免费,都有哪些好的动漫网站?
建站之星3.0如何解决常见操作问题?
如何用5美元大硬盘VPS安全高效搭建个人网站?
外汇网站制作流程,如何在工商银行网站上做外汇买卖?
网站设计制作公司地址,网站建设比较好的公司都有哪些?
制作充值网站的软件,做人力招聘为什么要自己交端口钱?
建站VPS能否同时实现高效与安全翻墙?
建站一年半SEO优化实战指南:核心词挖掘与长尾流量提升策略
如何自己制作一个网站链接,如何制作一个企业网站,建设网站的基本步骤有哪些?
javascript中对象的定义、使用以及对象和原型链操作小结
西安市网站制作公司,哪个相亲网站比较好?西安比较好的相亲网站?
如何在万网ECS上快速搭建专属网站?
C++如何使用std::optional?(处理可选值)
整蛊网站制作软件,手机不停的收到各种网站的验证码短信,是手机病毒还是人为恶搞?有这种手机病毒吗?
大型企业网站制作流程,做网站需要注册公司吗?
济南网站建设制作公司,室内设计网站一般都有哪些功能?
网站制作与设计教程,如何制作一个企业网站,建设网站的基本步骤有哪些?
如何在Mac上搭建Golang开发环境_使用Homebrew安装和管理Go版本
定制建站模板如何实现SEO优化与智能系统配置?18字教程
移动端手机网站制作软件,掌上时代,移动端网站的谷歌SEO该如何做?
如何打造高效商业网站?建站目的决定转化率
岳西云建站教程与模板下载_一站式快速建站系统操作指南
如何选购建站域名与空间?自助平台全解析
javascript基本数据类型及类型检测常用方法小结
建站为何优先选择香港服务器?
*请认真填写需求信息,我们会在24小时内与您取得联系。