Lock接口提供了方法Condition newCondition();用于获取对应锁的条件,可以在这个条件对象上调用监视器方法
可以理解为,原本借助于synchronized关键字以及锁对象,配备了一个监视器
而显式锁Lock与Condition则针对于一个锁对象,提供了多个监视器
尽管是提供了多个监视器,但是需要记住,是Lock接口提供方法才能够获取到条件对象,所以这些条件对象仍旧是绑定到某一把锁上的
我相信,只要理解了监视器的概念,对于Condition理解起来是不会存在任何难度的,因为本身就是另外一种实现方式
从下图可以直观的感受到Condition是作为Object监视器方法的另外实现
wait在这边叫做await
notify在这边叫做signal

等待

await

在监视器上等待
void await() throws InterruptedException;   ,看得出来,此方法是支持中断的
除非发生以下事件,否则将会持续等待
  • 其他某个线程调用此 Condition 的 signal() 方法,并且碰巧唤醒的是该线程
  • 其他某个线程调用此 Condition 的 signalAll() 方法;
  • 其他某个线程中断当前线程
  • “虚假唤醒”

awaitUninterruptibly

不支持中断的await方法,void awaitUninterruptibly();
从await()的介绍中看得出来,除非发生提到的四种情况,否则将会是等待状态
而void awaitUninterruptibly();则是await()的不可中断版本,也就是只会有三种情况会跳出等待
  • 其他某个线程调用此 Condition 的 signal() 方法,并且碰巧唤醒的是该线程
  • 其他某个线程调用此 Condition 的 signalAll() 方法;
  • 其他某个线程中断当前线程
  • “虚假唤醒”

awaitNanos

    long awaitNanos(long nanosTimeout) throws InterruptedException;
支持设置超时的等待,参数为等待的纳秒的long型数值
他在基于await的前提下,新增加了超时跳出,否则将会一直等待,他的跳出条件如下
  • 其他某个线程调用此 Condition 的 signal() 方法,并且碰巧唤醒的是该线程
  • 其他某个线程调用此 Condition 的 signalAll() 方法;
  • 其他某个线程中断当前线程
  • “虚假唤醒”
  • 已超过指定的等待时间(新增)
返回值
需要注意的是此方法的返回值,是一个long
我们设置了一个超时时间,那么到底用了多少秒,还剩下多少秒?这个返回值就是这意思:
(nanosTimeout - 实际花费时间)的估算值,如果小于等于0,表示没有剩余时长;如果大于0,可以用来确定如果等待返回了是否还需要继续等待?
比如,你在等朋友A,A说你等我一小时,于是你去睡觉了,结果你睡了半小时就被叫醒了,那么跟你本来要等的时间还差半小时
那还要不要继续等了?还是一定要等到总共一小时呢?
典型用法(来自API):
boolean aMethod(long timeout, TimeUnit unit) {
long nanos = unit.toNanos(timeout);
lock.lock();
try {
while (!conditionBeingWaitedFor()) {
if (nanos <= 0L)
return false;
nanos = theCondition.awaitNanos(nanos);
}
// ...
} finally {
lock.unlock();
}
}
上面的方法中,如果条件仍旧不满足,但是等待结束了(也就是等待了足够多的时间了),直接返回false;否则将会继续执行,直到等到最后一刻
ps:这种代码风格也就JDK常写,否者这种if形式,估计要被项目经理骂

await(long time, TimeUnit unit)

    boolean await(long time, TimeUnit unit) throws InterruptedException;
此方法也是设置超时时长的等待方法,第一个参数为时长个数,第二个参数为第一个参数的单位
他相当于awaitNanos方法的封装(此处是逻辑上看起来,而不是说就是这个方法的封装)
awaitNanos(unit.toNanos(time)) > 0
所以返回类型为boolean,显然true表示没有等待足够的时间;,false 表示等待了足够时间,也就是等待超时

awaitUntil

    boolean awaitUntil(Date deadline) throws InterruptedException;
awaitUntil类似于await(long time, TimeUnit unit),只不过不是设置超时时长,而是设置截止日期
逻辑上可以把他们理解为一回事,如果没有等待足够时长,那么返回true;如果等待超时那么返回false
常用的逻辑(来自API)
boolean aMethod(Date deadline) {
boolean stillWaiting = true;
lock.lock();
try {
while (!conditionBeingWaitedFor()) {
if (!stillWaiting)
return false;
stillWaiting = theCondition.awaitUntil(deadline);
}
// ...
} finally {
lock.unlock();
}
}
上面的代码中,如果等待了足够的时长(等待超时),那么就会返回false;如果还有剩余时间,继续等待
 
普通的await()方法和awaitUninterruptibly都是直白的等待,一个支持中断,一个不支持中断
有超时设置的三个方法:
awaitNanos、await(long time, TimeUnit unit)、awaitUntil
都是在await()的基础上对超时时长或者截止日期的设置使用
不过这几个方法会返回剩余的超时时长或者使用boolean指示是否还有剩余
所以如果条件不满足,如果还没等够时间,可以控制继续等待或者退出
而对于Object提供的wait方法,就不能做到这么灵活的控制,要么就条件不满足继续等待,要么醒来后继续做别的事情,没办法相对准确的控制“必须要等待一定的时长”,因为如果wait(一小时),5分钟后,被唤醒了,这个用掉了的五分钟(或者说还剩余55分钟,是不知道的)

唤醒

关于唤醒有与Object提供的类似的两个方法,他们的逻辑含义也是一样的,唤醒一个或者唤醒所有,概念上并没有太多需要注意的事情
void signal();
void signalAll();

总结

Condition本身就是Object中监视器概念的另外实现,所以监视器方法调用,也需要持有锁,也就是说:
调用Condition的await()和signal()等方法,都必须在lock保护之内,就是说必须在lock.lock()和lock.unlock之间才可以使用
await系列方法相对于Object提供了更加灵活的使用形式,signal和signalAll的逻辑含义可以认为完全一致
另外需要注意await方法与Object中的wait一样,都会释放当前持有的锁,所以醒来之后,会需要重新获取锁

java并发多线程显式锁Condition条件简介分析与监视器 多线程下篇(四)的更多相关文章

  1. java 并发多线程显式锁概念简介 什么是显式锁 多线程下篇(一)

    目前对于同步,仅仅介绍了一个关键字synchronized,可以用于保证线程同步的原子性.可见性.有序性 对于synchronized关键字,对于静态方法默认是以该类的class对象作为锁,对于实例方 ...

  2. Java并发之显式锁和隐式锁的区别

    Java并发之显式锁和隐式锁的区别 在面试的过程中有可能会问到:在Java并发编程中,锁有两种实现:使用隐式锁和使用显示锁分别是什么?两者的区别是什么?所谓的显式锁和隐式锁的区别也就是说说Synchr ...

  3. Java并发(十一):Condition条件

    先做总结: 1.为什么使用Condition条件? synchronized配合Object的wait().notify()系列方法可以实现等待/通知模式. Lock提供了条件Condition,对线 ...

  4. 六、显式锁和AQS

    显式锁和AQS 一.显式锁 ​ Synchronized 关键字结合对象的监视器,JVM 为我们提供了一种『内置锁』的语义,这种锁很简便,不需要我们关心加锁和释放锁的过程,我们只需要告诉虚拟机哪些代码 ...

  5. Java并发编程之显式锁机制

    我们之前介绍过synchronized关键字实现程序的原子性操作,它的内部也是一种加锁和解锁机制,是一种声明式的编程方式,我们只需要对方法或者代码块进行声明,Java内部帮我们在调用方法之前和结束时加 ...

  6. Java并发编程系列-(4) 显式锁与AQS

    4 显示锁和AQS 4.1 Lock接口 核心方法 Java在java.util.concurrent.locks包中提供了一系列的显示锁类,其中最基础的就是Lock接口,该接口提供了几个常见的锁相关 ...

  7. “全栈2019”Java多线程第三十二章:显式锁Lock等待唤醒机制详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  8. “全栈2019”Java多线程第三十一章:中断正在等待显式锁的线程

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  9. java并发编程(6)显式锁

    显式锁 一.Lock与ReentrantLock Lock提供了一种无条件的.可轮询的.定时的以及可中断的锁获取操作,所有的加锁和解锁方法都是显式的 ReentrantLock实现了Lock:并提供了 ...

随机推荐

  1. BZOJ4554: [Tjoi2016&Heoi2016]游戏 luoguP2825 loj2057

    题面描述:尽可能多的放置符合要求的炸弹. 分析: 在i,j处放置炸弹,则在第i行,上一个硬石头之后,下一个硬石头之前,第j列,上一个硬石头之后,下一个硬石头之前,不能再次放置炸弹. 首先,这个题,一看 ...

  2. Pandas之groupby( )用法笔记

    groupby官方解释 DataFrame.groupby(by=None, axis=0, level=None, as_index=True, sort=True, group_keys=True ...

  3. Applet 应用程序进行数字签名,对系统文件进行读写操作

    转:http://www.iteye.com/topic/154531 最近在研究applet,打算使用applet来开发一个上传文件上传控件,之前因为一直觉得applet的沙箱控制导致applet不 ...

  4. Postman----presets与环境变量的联合使用

    一.环境 在开发不同阶段,可能存在不同的环境(对我碰到的就是服务器地址/api版本/header信息等不一样),比如 debug环境和release环境,每次切换环境测试的时候都得重新配置url信息, ...

  5. Mysql存储过程 —— SEQUENCE的实现

    http://blog.csdn.net/crazylaa/article/details/5368447 创建sql语句: DROP TABLE IF EXISTS sequence; -- 建se ...

  6. hydra暴力破解ssh服务器密码

    概述 我都没想到,第一次暴力破解服务器密码.竟然是对自己的单位服务器出手..囧,因为还没来得及找测试部要来服务器登录密码,测试部负责人已经下班走了.后来又联系不上,这要更新代码,怎么办..于是就对测试 ...

  7. 《前端之路》之 Babel 下一代 JavaScript 语法编译器

    写本章的内容的出发点主要是 为了对于之前关于 JS 版本的一个总结,在之前的开发中,我们始终对于 ECMAScript 的版本的更新不够重视,以至于在后面的 开发过程中,我们始终会被各种新奇的语法打断 ...

  8. 微信小程序之滑动日历展示

    滑动日历效果 效果预览 实现要求:顶部固定悬浮的是获取未来一周的日期,分为上下两部分,上面部分显示星期,下面则显示具体日期.今天则显示今天,可点击头部具体日期,可向左向右滑动. 实现代码 顶部日历 页 ...

  9. 从css 3d说到空间坐标轴

    有一次我们说到掷骰子那个游戏,当时是用了一个steps属性+雪碧图来制作帧动画,这当然颇为不错,但其实一开始我想的不是这样的,我想的是用真的3d和动画去做,这个方案涉及到不少空间的知识,今天来给大伙好 ...

  10. Java - 静态代理详讲

    Java - 静态代理详讲 作者 : Stanley 罗昊 [转载请注明出处和署名,谢谢!] 写在前面:*此章内容比较抽象,所以需要结合实际操作进行讲解*                   *需要有 ...