全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

类似Object监视器方法的Condition接口(详解)

在《基于线程、并发的基本概念(详解)》中,我们利用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类操作锁的方法详解  # 第一个  # 所示  # 是一个  # 如下图  # 也就  # 则是  # 才会  # 给大家  # 并不代表  # 会将  # 基本概念  # 移除  # 的是  # 就会  # 是在  # 将会  # 只会  # 希望能  # 并将  # 仅仅是 


相关文章: 建站主机空间推荐 高性价比配置与快速部署方案解析  如何通过虚拟机搭建网站?详细步骤解析  招商网站制作流程,网站招商广告语?  建站之星云端配置指南:模板选择与SEO优化一键生成  购物网站制作公司有哪些,哪个购物网站比较好?  如何在Windows服务器上快速搭建网站?  高性价比服务器租赁——企业级配置与24小时运维服务  广州顶尖建站服务:企业官网建设与SEO优化一体化方案  建站之星官网登录失败?如何快速解决?  零服务器AI建站解决方案:快速部署与云端平台低成本实践  制作电商网页,电商供应链怎么做?  C#怎么创建控制台应用 C# Console App项目创建方法  如何高效生成建站之星成品网站源码?  网站网页制作电话怎么打,怎样安装和使用钉钉软件免费打电话?  网站图片在线制作软件,怎么在图片上做链接?  如何在Golang中使用encoding/gob序列化对象_存储和传输数据  如何选择网络建站服务器?高效建站必看指南  网站视频制作书签怎么做,ie浏览器怎么将网站固定在书签工具栏?  建设网站制作价格,怎样建立自己的公司网站?  如何通过智能用户系统一键生成高效建站方案?  如何正确选择百度移动适配建站域名?  建站之星导航菜单设置与功能模块配置全攻略  免费网站制作模板下载,除了易企秀之外还有什么H5平台可以制作H5长页面,最好是免费的?  如何在搬瓦工VPS快速搭建网站?  建站之星会员如何解锁更多建站功能?  css网站制作参考文献有哪些,易聊怎么注册?  网站制作大概要多少钱一个,做一个平台网站大概多少钱?  官网自助建站平台指南:在线制作、快速建站与模板选择全解析  网站制作大概多少钱一个,做一个平台网站大概多少钱?  如何在Golang中处理模块冲突_解决依赖版本不兼容问题  b2c电商网站制作流程,b2c水平综合的电商平台?  如何在云主机上快速搭建网站?  做企业网站制作流程,企业网站制作基本流程有哪些?  云南网站制作公司有哪些,云南最好的招聘网站是哪个?  怎么将XML数据可视化 D3.js加载XML  建站之星备案是否影响网站上线时间?  攀枝花网站建设,攀枝花营业执照网上怎么年审?  无锡制作网站公司有哪些,无锡优八网络科技有限公司介绍?  建站三合一如何选?哪家性价比更高?  如何快速生成橙子建站落地页链接?  平台云上自主建站:模板化设计与智能工具打造高效网站  c# F# 的 MailboxProcessor 和 C# 的 Actor 模型  如何制作一个表白网站视频,关于勇敢表白的小标题?  如何快速查询域名建站关键信息?  历史网站制作软件,华为如何找回被删除的网站?  如何在企业微信快速生成手机电脑官网?  网站制作话术技巧,网站推广做的好怎么话术?  python的本地网站制作,如何创建本地站点?  如何通过PHP快速构建高效问答网站功能?  武汉外贸网站制作公司,现在武汉外贸前景怎么样啊? 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。