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 ...
随机推荐
- 最新豆瓣top250爬虫案例代码分析[注释齐全]
导入包 # json包 import json #正则表达式包 import re import requests from requests import RequestException 定义爬取 ...
- JAVA语言基础组成(2)
函数 函数的定义 1.什么是函数? 函数就是定义在类中的具有特定功能的一段独立小程序.函数也称为方法. 2.函数的格式: 修饰符 返回值类型 函数名(参数类型 形式参数1,参数类型 形式参数2,.. ...
- Spring源码 05 IOC 注解方式
参考源 https://www.bilibili.com/video/BV1tR4y1F75R?spm_id_from=333.337.search-card.all.click https://ww ...
- java-异常处理和线程的一些简单方法及使用
1.1 子类重写父类含有throws声明异常抛出的方法时的规则: 1.允许不再抛出任何异常. 2.仅抛出部分异常. 3.抛出父类方法抛出异常的子类型异常. 4.不可以抛出额外异常. 5.不能抛出父类方 ...
- 基础2:js创建对象的多种方式
js创建对象的多种方式 1. 工厂模式 function createPerson(name) { var o = new Object() 0.name = name return o } var ...
- Linux 安装 Tomcat 详细教程
Linux 安装Tomcat详细步骤 1. 前往tomcat官网复制下载链接, tomcat官网地址:https://tomcat.apache.org/ 2. 进入到指定目录,使用 wget 命令下 ...
- [CF1526F] Median Queries(交互 / 构造)
题面 这是一道交互题. 有一个未知的长度为 N \tt N N 的排列 P \tt P P,已知 P 1 < P 2 \tt P_1 < P_2 P1<P2 . 每次询问格式为 ...
- 【java】学习路线14-抽象类、多态
/*抽象类 abstractabstract class A{ }注意abstract类中不一定需要有abstract方法但是有abstract方法的类中,该类一定是abstract方法抽象类不 ...
- E - Road Reduction
E - Road Reduction (atcoder.jp) 题意:一棵树n个点,m条路, di表示1-i的距离,问怎么选择边可以使得d2+...dn最短. 题解: 很明显,就是直接套最短路板子,判 ...
- ELK技术-IK-中文分词器
1.背景 1.1 简介 ES默认的分词器对中文分词并不友好,所以一般会安装中文分词插件,以便能更好的支持中文分词检索. 本例参考文档:<一文教你掌握IK中文分词> 1.2 IK分词器 IK ...