实现原理_Condition 实现原理
Condition 实现原理
说 Codition 前,需要说下 ConditioObject。 ConditionObject 是同步器 AbstractQueuedSynchronzied 的内部类,因为 Condition 的操作需要关联的锁。 ArrayBlockingQueue 就是 Condition 的具体应用。 Object 中其实 也有 wait ,notify ,notifyAll 等操作, Condition 相当于将 wait ,notify ,notifyAll 转换成想要的对象,将比较难懂的同步操作变成直观可控的对象行为。
应用场景 ArrayBlockingQueue
ArrayBlockingQueue 的构造函数。
/** Main lock guarding all access */
final ReentrantLock lock;/** Condition for waiting takes */
private final Condition notEmpty;/** Condition for waiting puts */
private final Condition notFull;
public ArrayBlockingQueue(int capacity, boolean fair) {if (capacity <= 0)throw new IllegalArgumentException();this.items = new Object[capacity];lock = new ReentrantLock(fair);notEmpty = lock.newCondition();notFull = lock.newCondition();
}
通过构造函数,可以看到 Condition 的创建时需要关联锁的。
从队列中去取出(take)数据 。
public E take() throws InterruptedException {final ReentrantLock lock = this.lock;lock.lockInterruptibly();try {while (count == 0)notEmpty.await();return dequeue();} finally {lock.unlock();}}
往队列中加入数据 enqueue
private void enqueue(E x) {// assert lock.getHoldCount() == 1;// assert items[putIndex] == null;final Object[] items = this.items;items[putIndex] = x;if (++putIndex == items.length)putIndex = 0;count++;notEmpty.signal();}
可以看主要用了 await signal 等方法。具体代表什么含义?
Condition 实现主要包含三个部分:等待队列、等待、通知。
如果了解 AQS 原理可以知道, AQS 中有个同步队列的概念。
等待队列
等待队列和同步队列类似,都是一个 FIFO 队列。队列上每个节点包含一个线程引用,该线程就是 Condition 对象上的等待线程。等待队列结构如下:
Condition 等待队列,也是包含首节点(firstWaiter),和尾节点(tailWaiter),如果一个线程调用了 Condition.await() 方法。那么该线程将会释放锁,并以当前线程构造节点加入等待队列并进入等待状态。
Object 监视器模型
Object 监视器模型 包含了一个同步多路和多个等待队列,结构如下所示:
等待
当调用 Condition 的 await() 方法(或者以 await开头的方法),会使得当前线程进入等待队列,并且释放锁,同时线程的状态变为等待状态。
public final void await() throws InterruptedException {if (Thread.interrupted())throw new InterruptedException();// 当前线程加入等待队列 Node node = addConditionWaiter();// 释放同步状态,也就是释放锁int savedState = fullyRelease(node);int interruptMode = 0;// node 不在节点中会一直 park 阻塞下去。达到等待的效果。while (!isOnSyncQueue(node)) {LockSupport.park(this);if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)break;}if (acquireQueued(node, savedState) && interruptMode != THROW_IE)interruptMode = REINTERRUPT;if (node.nextWaiter != null) // clean up if cancelledunlinkCancelledWaiters();if (interruptMode != 0)reportInterruptAfterWait(interruptMode);}
调用该方法的线程成功获得了锁的线程,也就是同步队列的首节点,该方法将会将该线程构造成节点并加入等待队列中,然后释放同步状态,唤醒同步队列中的后续节点,然后当前节点会进入等待状态。要注意的是,如果等地队列中的节点被唤醒,唤醒节点的线程开始尝试获取同步状态。但是如果不是通过 Condition.signal 进行唤醒的,而是对等待线程进行中断,那么会抛出 InterruptedException。
调用 Condition signal 方法后,当前线程会加入到等待队列,如下图所示:
通知
调用 Condition.signal() 方法,将会唤醒等待队列中等待时间最长的节点(首节点),在唤醒节点之前,会将节点移动到同步队列中。
public final void signal() {if (!isHeldExclusively())throw new IllegalMonitorStateException();Node first = firstWaiter;if (first != null)doSignal(first);}
final boolean transferForSignal(Node node) {/** If cannot change waitStatus, the node has been cancelled.*/if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))return false;/** Splice onto queue and try to set waitStatus of predecessor to* indicate that thread is (probably) waiting. If cancelled or* attempt to set waitStatus fails, wake up to resync (in which* case the waitStatus can be transiently and harmlessly wrong).*/Node p = enq(node);int ws = p.waitStatus;if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))LockSupport.unpark(node.thread);return true;}
需要注意的是,调用该方法的前置条件是当前线程必须获得了锁,可以看到 Signal() 方法进行了 isHeldExclusively 检查,判断是否获得了锁,接着获取等待队列的首节点,将其移动到同步队列并使用 LockSupport 唤醒节点中的线程。
节点从等待队列,移动到同步队列的操作过程如下:
通过调用同步器的 enq(Node node) 方法,等待队列中的头节点线程安全地移动到同步队列中,当节点移动到同步队列后,当前线程再使用 LockSupport 唤醒该节点的线程。
被唤醒的线程,将从 await() 方法中的 while 循环中退出。从 await 方法看
// 当前节点已经在同步队列了,不会在循环下去了while (!isOnSyncQueue(node)) {LockSupport.park(this);if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)break;}
随后调用同步器的 acquireQueued() 方法加入到同步队列的竞争中。
final boolean acquireQueued(final Node node, int arg) {boolean failed = true;try {boolean interrupted = false;for (;;) {final Node p = node.predecessor();if (p == head && tryAcquire(arg)) {setHead(node);p.next = null; // help GCfailed = false;return interrupted;}if (shouldParkAfterFailedAcquire(p, node) &&parkAndCheckInterrupt())interrupted = true;}} finally {if (failed)cancelAcquire(node);}}
成功获取同步状态(获得锁)之后,被唤醒的线程,景从先前调用的 await 方法返回。此时线程已经成功获得了锁。
总结
本文剖析了一下 Condition 的实现原理,等待队列,等待,通知的实现原理。
程序员开发者社区
实现原理_Condition 实现原理相关推荐
- grpc通信原理_容器原理架构详解(全)
目录 1 容器原理架构 1.1 容器与虚拟化 1.2 容器应用架构 1.3 容器引擎架构 1.4 Namespace与Cgroups 1.5 容器镜像原理 2 K8S原理架构 2.1 K8S主要功能 ...
- BC之SC:区块链之智能合约——与传统合约的比较以及智能合约模型部署原理、运行原理相关配图
BC之SC:区块链之智能合约--与传统合约的比较以及智能合约模型部署原理.运行原理相关配图 目录 SC与传统合约的比较 SC模型部署原理.运行原理 SC与传统合约的比较 1.传统合约VS智能合约 特 ...
- 真香定律!Android动态换肤实现原理解析,原理+实战+视频+源码
自己项目中一直都是用的开源的xUtils框架,包括BitmapUtils.DbUtils.ViewUtils和HttpUtils四大模块,这四大模块都是项目中比较常用的.最近决定研究一下xUtils的 ...
- mapreduce原理_Hbase Bulkload 原理面试必备
当需要大批量的向Hbase导入数据时,我们可以使用Hbase Bulkload的方式,这种方式是先生成Hbase的底层存储文件 HFile,然后直接将这些 HFile 移动到Hbase的存储目录下.它 ...
- kafka分区与分组原理_Kafka工作原理
Kafka工作原理 Kafka工作原理 4.1. topic和消息 4.2. Producer 4.3. Consumer 4.4. Kafka核心特性 4.5. consumer.consumer ...
- 【重难点】【JUC 04】synchronized 原理、ReentrantLock 原理、synchronized 和 Lock 的对比、CAS 无锁原理
[重难点][JUC 04]synchronized 原理.ReentrantLock 原理.synchronized 和 Lock 的对比.CAS 无锁原理 文章目录 [重难点][JUC 04]syn ...
- bootloader功能介绍/时钟初始化设置/串口工作原理/内存工作原理/NandFlash工作原理...
bootloader功能介绍 初始化开发板上主要硬件(时钟,内存,硬盘), 把操作系统从硬盘拷贝到内存,然后让cpu跳转到内存中执行操作系统. boot阶段 1.关闭影响CPU正常执行的外设 -关闭看 ...
- TRIZ系列-创新原理-14~15-曲面化原理和动态性原理
一.曲面化原理的表述如下 1)用曲线部件代替直线部件,用球面代替平面,用球体代替立方体: 2)采用滚筒,球体,螺旋体: 3)利用离心力,用旋转物体代替直线运动 由于TRIZ的创新原理是基于专利分析的基 ...
- 分类计数原理与分步计数原理_分类计数原理与分步计数原理
分类计数原理与分步计数原理 <分类计数原理与分步计数原理 ( 一 ) >教学设计 柳州地区民族高级中学 覃艳莉 相关教材 : 人民教育出版社的全日制普通高级中学教科书 ( 必修 ) < ...
最新文章
- 「小程序JAVA实战」小程序的举报功能开发(68)
- linux lsof/netstat查看进程和端口号相关命令:
- 发言倒计时器_单面会议计时器 会议发言倒计时器
- 2020五一数学建模比赛总结
- 测试显卡cpu中文软件,显卡信息检测工具(GPUinfo)
- 信息系统分析与设计----系统分析概述
- ARM 汇编详解 -- 体系结构与编程
- c语言 获取硬盘号,C语言获得硬盘序列号
- 【Struck】论文阅读笔记
- numpy dot用法解释
- 滴滴快车奖励政策,高峰奖励,翻倍奖励,按成交率,指派单数分级(10月17日~10月23日)...
- 最近在装修房子,展示下最近成果
- 中国书法名词解释大全
- 双网卡同时上网如何设置 双网卡同时上内外网络
- 无忧启动源码 仿音速启动
- nginx+createrepo搭建局域网yum源
- 央视报道:全国22家奶粉厂家69批次…
- 项目一 认识Linux 操作系统
- 单片机控制继电器电路 程序就很简单了 做一个口的输出就可以了
- 一时兴起之matlab学习记录