JUC.Condition学习笔记[附详细源码解析]
目录
I.初始化状态 II.await()操作 III.signal()操作
Condition的数据结构
线程何时阻塞和释放
await()方法
signal()和signalAll()方法
JUC提供了Lock可以方便的进行锁操作,但是有时候我们也需要对线程进行条件性的阻塞和唤醒,这时我们就需要condition条件变量,它就像是在线程上加了多个开关,可以方便的对持有锁的线程进行阻塞和唤醒。
Condition的概念
Condition实质上是被绑定到一个锁上。
大体实现流程

3个主要方法
Condition的数据结构
线程何时阻塞和释放
await方法
Code
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
;
// 4.为什么会有在AQS的等待队列的判断? // 解答:signal操作会将Node从Condition队列中拿出并且放入到等待队列中去,在不在AQS等待队列就看signal是否执行了 // 如果不在AQS等待队列中,就park当前线程,如果在,就退出循环,这个时候如果被中断,那么就退出循环 ) break; } // 5.这个时候线程已经被signal()或者signalAll()操作给唤醒了,退出了4中的while循环 // ) reportInterruptAfterWait(interruptMode); } |
signal和signalAll方法
await*()清楚了,现在再来看signal/signalAll就容易多了。按照signal/signalAll的需求,就是要将Condition.await*()中FIFO队列中第一个Node唤醒(或者全部Node)唤醒。尽管所有Node可能都被唤醒,但是要知道的是仍然只有一个线程能够拿到锁,其它没有拿到锁的线程仍然需要自旋等待,就上上面提到的第4步(acquireQueued)。
Code
1
2 3 4 5 6 7 |
public final void signal() {
if (!isHeldExclusively()) throw new IllegalMonitorStateException(); Node first = firstWaiter; if (first != null) doSignal(first); } |
这里先判断当前线程是否持有锁,如果没有持有,则抛出异常,然后判断整个condition队列是否为空,不为空则调用doSignal方法来唤醒线程,看看doSignal方法都干了一些什么:
Code
1
2 3 4 5 6 7 8 |
private void doSignal(Node first) {
do { if ( (firstWaiter = first.nextWaiter) == null) lastWaiter = null; first.nextWaiter = null; } while (!transferForSignal(first) && (first = firstWaiter) != null); } |
Code
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
))
return false; /* |
Code
1
2 3 4 5 6 7 8 9 |
private void doSignalAll(Node first) {
lastWaiter = firstWaiter = null; do { Node next = first.nextWaiter; first.nextWaiter = null; transferForSignal(first); first = next; } while (first != null); } |
这个方法就相当于把Condition队列中的所有Node全部取出插入到等待队列中去。
Condition应用示例:生产者和消费者
Condition
实例实质上被绑定到一个锁上。要为特定 Lock
实例获得
Condition
实例,请使用其 newCondition()
方法。在最后我们来看一个应用示例
Code
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
; i++) {
try { get(); } catch (InterruptedException e) { } } } } public static void main(String[] args) { |
JUC.Condition学习笔记[附详细源码解析]的更多相关文章
- JUC.Lock(锁机制)学习笔记[附详细源码解析]
锁机制学习笔记 目录: CAS的意义 锁的一些基本原理 ReentrantLock的相关代码结构 两个重要的状态 I.AQS的state(int类型,32位) II.Node的waitStatus 获 ...
- Laravel学习笔记之Session源码解析(上)
说明:本文主要通过学习Laravel的session源码学习Laravel是如何设计session的,将自己的学习心得分享出来,希望对别人有所帮助.Laravel在web middleware中定义了 ...
- Laravel学习笔记之Session源码解析(下)
说明:在中篇中学习了session的CRUD增删改查操作,本篇主要学习关闭session的相关源码.实际上,在Laravel5.3中关闭session主要包括两个过程:保存当前URL到session介 ...
- Laravel学习笔记之Session源码解析(中)
说明:在上篇中学习了session的启动过程,主要分为两步,一是session的实例化,即\Illuminate\Session\Store的实例化:二是从session存储介质redis中读取id ...
- Hadoop学习笔记(10) ——搭建源码学习环境
Hadoop学习笔记(10) ——搭建源码学习环境 上一章中,我们对整个hadoop的目录及源码目录有了一个初步的了解,接下来计划深入学习一下这头神象作品了.但是看代码用什么,难不成gedit?,单步 ...
- memcached学习笔记——存储命令源码分析下篇
上一篇回顾:<memcached学习笔记——存储命令源码分析上篇>通过分析memcached的存储命令源码的过程,了解了memcached如何解析文本命令和mencached的内存管理机制 ...
- memcached学习笔记——存储命令源码分析上篇
原创文章,转载请标明,谢谢. 上一篇分析过memcached的连接模型,了解memcached是如何高效处理客户端连接,这一篇分析memcached源码中的process_update_command ...
- Sping学习笔记(一)----Spring源码阅读环境的搭建
idea搭建spring源码阅读环境 安装gradle Github下载Spring源码 新建学习spring源码的项目 idea搭建spring源码阅读环境 安装gradle 在官网中下载gradl ...
- [Golang学习笔记] 03 库源码文件
库源码文件:不能被直接运行的源码文件,它仅用于存放程序实体,这些程序实体可以被其他代码使用. 代码包声明的基本规则: 1. 同目录下的源码文件的代码包声明语句要一致.也就是说,它们要同属于一个代码包( ...
随机推荐
- 时间戳 JavaScript parse() 方法 处理技巧
返回1970/01/01至2012/3/21之间的毫秒数: var d = Date.parse("March 21, 2012"); d 输出结果: 1332259200000 ...
- C++语法
http://stackoverflow.com/questions/4269034/what-is-the-meaning-of-prepended-double-colon
- tomcat跨域请求
tomcat A请求tomcat B中的数据(本人是在同一台机器上2个tomcat端口不同,在不同机器上有时间会测得) 博主用的是ajax请求 在A 请求B中数据,用下面的方法可以 在被请求的tomc ...
- 错误: 程序包com.sun.istack.internal不存在
eclipse下maven打包是出现如下错误: [ERROR] D:\code-old\daba_user_mvn\src\main\java\com\dada\transaction\service ...
- Python 各进制间的转换(转)
转载自:http://blog.chinaunix.net/uid-21516619-id-1824975.html python 2.6以后内置函数#10进制转为2进制>>> bi ...
- IT荐书|10个最“牛叉”的代码注释
下面是 网友针对“你看到过的最好的代码注释是什么样的?”这个问题给出的回答的前10条: 1. // 亲爱的维护者: // 如果你尝试了对这段程序进行‘优化’, // 并认识到这种企图是大错特错,请增加 ...
- zepto.js使用前注意
API:http://www.css88.com/doc/zeptojs_api/ 一.建议:不要从官网下载,而是从 Github 下载了源代码之后自己 Build 一个版本,这样你可以自行挑选适合的 ...
- Windows消息机制详解
消息是指什么? 消息系统对于一个win32程序来说十分重要,它是一个程序运行的动力源泉.一个消息,是系统定义的一个32位的值,他唯一的定义了一个事件,向 Windows发出一个通知,告诉应用 ...
- OAF_开发系列24_实现OAF更新记录显示Record History(案例)
20150716 Created By BaoXinjian
- 常用SQL Server日期格式化
Select CONVERT(varchar(100), GETDATE(), 8): 10:57:46 Select CONVERT(varchar(100), GETDATE(), 24): 10 ...