Condition介绍
Condition
Condition是一种多线程通信工具,表示多线程下参与数据竞争的线程的一种状态,主要负责多线程环境下对线程的挂起和唤醒工作。
方法
// ========== 阻塞 ==========
// 造成当前线程在接到信号或被中断之前一直处于等待状态。
void await() throws InterruptedException;
// 造成当前线程在接到信号之前一直处于等待状态。【注意:该方法对中断不敏感】。
void awaitUninterruptibly();
// 造成当前线程在接到信号、被中断或到达指定等待时间之前一直处于等待状态。
//返回值表示剩余时间,如果在`nanosTimeout` 之前唤醒,那么返回值 `= nanosTimeout - 消耗时间` ,
//如果返回值 `<= 0` ,则可以认定它已经超时了
long awaitNanos(long nanosTimeout) throws InterruptedException;
// 造成当前线程在接到信号、被中断或到达指定等待时间之前一直处于等待状态。
boolean await(long time, TimeUnit unit) throws InterruptedException;
// 造成当前线程在接到信号、被中断或到达指定最后期限之前一直处于等待状态。
//如果没有到指定时间就被通知,则返回 true ,否则表示到了指定时间,返回返回 false 。
boolean awaitUntil(Date deadline) throws InterruptedException;
// ========== 唤醒 ==========
// 唤醒一个等待线程。该线程从等待方法返回前必须获得与Condition相关的锁。
void signal();
// 唤醒所有等待线程。能够从等待方法返回的线程必须获得与Condition相关的锁。
void signalAll();
原理
Condition 内部维护一个条件队列,在获取锁的情况下,线程调用 await,线程会被放置在条件队列中并被阻塞。直到调用 signal、signalAll 唤醒线程,此后线程唤醒,会放入到 AQS 的同步队列,参与争抢锁资源。
AQS是AbstractQueuedSynchronizer的简称,翻译过来就是抽象队列同步器.
await
调用condition.await()方法会使当前线程进入等待队列并释放锁,同时线程变为等待状态。当从await()方法返回时,一定是获得与condition相关联的锁。
此时AQS主要执行以下动作:
线程1把自己包装成节点,waitStatus设为CONDITION(-2),追加到ConditionObject中的条件队列(每个ConditionObject有一个自己的条件队列);
线程1释放锁,把state设置为0;
然后唤醒等待队列中head节点的下一个节点;

//await
public final void await() throws InterruptedException {
// 1、线程如果中断,那么抛出异常
if (Thread.interrupted())
throw new InterruptedException();
// 2、将当前线程包装成为一个Node节点,加入FIFO队列中
Node node = addConditionWaiter();
// 3、释放锁
int savedState = fullyRelease(node);
int interruptMode = 0;
// 4、判断节点是否在同步队列(注意非Condition队列)中,如果没有,则挂起当前线程,因为该线程尚未具备数据竞争资格
while (!isOnSyncQueue(node)) {
// 5、挂起线程
LockSupport.park(this);
// 6、中断直接返回
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
}
// 7、参与数据竞争(非中断时执行)
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
// 清理条件队列中状态为cancelled的节点
if (node.nextWaiter != null) // clean up if cancelled
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
}
signal
另一个线程执行了 condition1.signal之后,主要是做了以下事情:
把条件队列中的第一个节点追加到等待队列中;
把等待队列原来尾节点的waitStatus设置为SIGNAL。
然后继续处理自己的事情,自己的事情处理完成之后,会释放锁,唤醒等待队列中head节点的下一个节点线程进行工作。

public final void signal() {
// 调用signal的线程必须持有独占锁
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
Node first = firstWaiter;
if (first != null)
doSignal(first);
}
private void doSignal(Node first) {
do {
// 因为first马上就要被转移到同步队列了,所以将first.nextWaiter,作为新的firstWatier。
if ( (firstWaiter = first.nextWaiter) == null)
lastWaiter = null;
//切断和等待队列的关联
first.nextWaiter = null;
// 如果转移不成功且还有后续节点,那么继续后续节点的转移
} while (!transferForSignal(first) &&
(first = firstWaiter) != null);
}
final boolean transferForSignal(Node node) {
// 判断节点是否已经在之前被取消了
if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
return false;
// 调用 enq 添加到 同步队列的尾部
Node p = enq(node);
int ws = p.waitStatus;
// node 的上一个节点 修改为 SIGNAL 这样后续就可以唤醒自己了
if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
LockSupport.unpark(node.thread);
return true;
}
使用示例
public class LockConditionDemo {
private static ReentrantLock lock = new ReentrantLock();
private static Condition condition = lock.newCondition();
public static void main(String[] args) throws InterruptedException {
Thread threadA = new Thread(() -> {
System.out.println("threadA start");
lock.lock();
System.out.println("threadA getLock Running");
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
lock.unlock();
System.out.println("threadA end");
});
Thread threadB = new Thread(() -> {
System.out.println("threadB start");
lock.lock();
System.out.println("threadB getLock Running");
condition.signal();
lock.unlock();
System.out.println("threadB end");
});
threadA.start();
TimeUnit.SECONDS.sleep(2);
threadB.start();
}
}
threadA start
threadA getLock Running
threadB start
threadB getLock Running
threadB end
threadA end
Condition介绍的更多相关文章
- ReentrantLock等待通知机制Condition介绍
Object类中的wait(),notify()和notifyAll()可以实现线程的等待通知模型,同样在ReentrantLock中可以借助Condition来完成这种机制.本篇就简要介绍Condi ...
- java中Condition类的详细介绍(详解)
已找不到原文了,还望原文博主看到能告诉小白一下,一定标注原文地址 一 condition 介绍及demo Condition是在java 1.5中才出现的,它用来替代传统的Object的wait(). ...
- Java多线程系列--“JUC锁”06之 Condition条件
概要 前面对JUC包中的锁的原理进行了介绍,本章会JUC中对与锁经常配合使用的Condition进行介绍,内容包括:Condition介绍Condition函数列表Condition示例转载请注明出处 ...
- Java基础篇——线程、并发编程知识点全面介绍(面试、学习的必备索引)
原创不易,如需转载,请注明出处https://www.cnblogs.com/baixianlong/p/10739579.html,希望大家多多支持!!! 一.线程基础 1.线程与进程 线程是指进程 ...
- Java - "JUC"之Condition源码解析
Java多线程系列--“JUC锁”06之 Condition条件 概要 前面对JUC包中的锁的原理进行了介绍,本章会JUC中对与锁经常配合使用的Condition进行介绍,内容包括:Condition ...
- Condition接口
<Java并发编程艺术>读书笔记 Condition介绍 任意一个Java对象,都拥有一组监视器方法(定义在java.lang.Object中),主要包括wait().wait(long ...
- Java多线程系列 JUC锁06 Condition条件
Condition介绍 Condition中提供了一组类似于Object中的监视器方法.与Lock配合可以完成等待通知模式. Lock lock = new ReentrantLock(); Cond ...
- concurrent(四)Condition
参考文档:Java多线程系列--“JUC锁”06之 Condition条件:http://www.cnblogs.com/skywang12345/p/3496716.html Condition介绍 ...
- Java锁--Condition
转载请注明出处:http://www.cnblogs.com/skywang12345/p/3496716.html Condition介绍 Condition的作用是对锁进行更精确的控制.Condi ...
随机推荐
- Taurus.MVC V3.0.3 微服务开源框架发布:让.NET 架构在大并发的演进过程更简单。
前方: 开源地址:https://github.com/cyq1162/Taurus.MVC 上篇文章介绍过:工业制造行业的低代码开发平台思维架构图 规划中涉及到了微服务,近些天经过努力和不断的代码与 ...
- react学习1-jsx语法注意点
* 1.定义虚拟DOM不要写引号 * 2.标签中使用js表达式的时候,要使用{} * 3.样式类名指定要使用className * 4.要使用内联样式的话,要使用style={{key:"v ...
- 分享俩个js数组比较少用的方法join与from
1:array.join 用于将数组中的所有元素转化为字符串 例: var arr = ["one", "two", "four"]; va ...
- 如何构建 Apache DolphinScheduler 的 Docker 镜像
继昨日发布第一个 [官方 Docker 镜像] 后,有几位小伙伴私信想自己进行编译,这里也将 Docker 的主要贡献者文禾同学整理的文档进行分享.以下是全文内容: 您能够在类 Unix 系统和 Wi ...
- Taurus.MVC WebAPI 入门开发教程8:WebAPI文档与自动化测试。
系列目录 1.Taurus.MVC WebAPI 入门开发教程1:框架下载环境配置与运行. 2.Taurus.MVC WebAPI 入门开发教程2:添加控制器输出Hello World. 3.Tau ...
- React报错之JSX element type does not have any construct or call signatures
正文从这开始~ 总览 当我们试图将元素或react组件作为属性传递给另一个组件,但是属性的类型声明错误时,会产生"JSX element type does not have any con ...
- 60行自己动手写LockSupport是什么体验?
60行自己动手写LockSupport是什么体验? 前言 在JDK当中给我们提供的各种并发工具当中,比如ReentrantLock等等工具的内部实现,经常会使用到一个工具,这个工具就是LockSupp ...
- Java SE 11 新增特性
Java SE 11 新增特性 作者:Grey 原文地址:Java SE 11 新增特性 源码 源仓库: Github:java_new_features 镜像仓库: GitCode:java_new ...
- 一文带你认知定时消息发布RocketMQ
摘要:DMS任意时间定时消息能力发布. DMS是华为云的分布式消息中间件服务.适用于解决分布式架构中的系统解耦.跨系统跨地域数据流通.分布式事务协调等难题,协助构建优雅的现代化应用架构,提供可兼容 K ...
- ettercap之dns欺骗攻击
前言:攻击机(kali)和受害机(win7)需在同一网段下 1.首先创建一个钓鱼克隆网站,这里我就利用CS来弄了 2.对Ettercap的dns文件进行编辑 3.开启ettercap 4.去受害机看看 ...