Condition的await-signal流程详解(转)
上一篇文章梳理了condtion,其中侧重流程,网上看到这篇文章文章介绍的很细。值得学习。特意转载过来。
转载请注明出处:http://blog.csdn.net/luonanqin
转载路径:http://blog.csdn.net/bohu83/article/details/51107870
上一篇讲了ReentrantLock的lock-unlock流程,今天这篇讲讲Condition的await-signal流程。
Condition类图:
- Condition接口包含了多种await方式和两个通知方法
- ConditionObject实现了Condition接口,是AbstractQueuedSynchronizer的内部类
- Reentrantlock的newCondition方法返回与某个lock实例相关的Condition对象
和release队列一样,Condition队列也是虚拟队列,每个Node通过nextWaiter进行关联。因为Condition Node要变为release Node才可以解除阻塞,所以不需要prevWaiter,这一点下面会有说明。
大概的整个过程是:
调用await的线程都会进入一个Condition队列。调用signal的线程每一次都会从firstWaiter开始找出未取消的Condition Node放到release队列里,然后调用signal的线程在await或者unlock的时候执行release方法才有机会将其解除阻塞。相对于lock-unlock,正常的流程要简单一些,但是对于中断处理会更为复杂。
先看看调用await()至阻塞的过程
如图所示,该过程可分为三个步骤:
- 新建Condition Node包装线程,加入Condition队列
- 释放当前线程占用的锁
- 阻塞当前线程
// AbstractQueuedSynchronizer.ConditionObject.class
final boolean isOnSyncQueue(Node node) {
// 当进入Condition队列时,waitStatus肯定为CONDITION,如果同时别的线程调用signal,Node会从Condition队列中移除,并且移除时会清除CONDITION状态。
// 从移除到进入release队列,中间这段时间prev必然为null,所以还是返回false,即被park
if (node.waitStatus == Node.CONDITION || node.prev == null)
return false;
// 当别的线程进入release队列时,会和前一个Node建立前后关系,所以如果next存在,说明一定在release队列中
if (node.next != null) // If has successor, it must be on queue
return true;
/*
* node.prev can be non-null, but not yet on queue because
* the CAS to place it on queue can fail. So we have to
* traverse from tail to make sure it actually made it. It
* will always be near the tail in calls to this method, and
* unless the CAS failed (which is unlikely), it will be
* there, so we hardly ever traverse much.
*/
// 可能该Node刚刚最后一个进入release队列,所以是tail,其next必然是null,所以需要从队尾向前查找
return findNodeFromTail(node);
}
signal()流程图
// AbstractQueuedSynchronizer.ConditionObject.class
final boolean transferForSignal(Node node) {
/*
* If cannot change waitStatus, the node has been cancelled.
*/
// 如果改变waitStatus失败,说明已经被取消,没必要再进入release队列了。外部再循环找到一个Condition Node
// 如果改变waitStatus成功,但是之后又被取消会怎么样?没关系,虽然已经进入release队列了,但是release方法里的unpark操作会跳过已取消的Node。这里的检查只是为了减少unpark时不必要的工作
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).
*/
// p是该Node的前驱
Node p = enq(node);
int ws = p.waitStatus;
// 这里影响设置waitStatus只可能发生于线程被取消,那时会调用cancelAcquire方法将waitStatus设置为CANCEL,但它不是CAS的
if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
LockSupport.unpark(node.thread);
return true;
}
我们可以看到,signal方法只是将Node修改了状态,并没有唤醒线程。要将修改状态后的Node唤醒,一种是再次调用await(),一种是调用unlock()。这两个方法内部都会执行release方法对release队列里的Node解除阻塞,关于这点我在上一篇文章里已经说明了。
之后有时间我会把一些中断处理也用流程图描述下发出来。
Condition的await-signal流程详解(转)的更多相关文章
- C++的性能C#的产能?! - .Net Native 系列《二》:.NET Native开发流程详解
之前一文<c++的性能, c#的产能?!鱼和熊掌可以兼得,.NET NATIVE初窥> 获得很多朋友支持和鼓励,也更让我坚定做这项技术的推广者,希望能让更多的朋友了解这项技术,于是先从官方 ...
- [nRF51822] 5、 霸屏了——详解nRF51 SDK中的GPIOTE(从GPIO电平变化到产生中断事件的流程详解)
:由于在大多数情况下GPIO的状态变化都会触发应用程序执行一些动作.为了方便nRF51官方把该流程封装成了GPIOTE,全称:The GPIO Tasks and Events (GPIOTE) . ...
- 迅为4412开发板Linux驱动教程——总线_设备_驱动注册流程详解
本文转自:http://www.topeetboard.com 视频下载地址: 驱动注册:http://pan.baidu.com/s/1i34HcDB 设备注册:http://pan.baidu.c ...
- Linux启动流程详解【转载】
在BIOS阶段,计算机的行为基本上被写死了,可以做的事情并不多:一般就是通电.BIOS.主引导记录.操作系统这四步.所以我们一般认为加载内核是linux启动流程的第一步. 第一步.加载内核 操作系统接 ...
- iOS 组件化流程详解(git创建流程)
[链接]组件化流程详解(一)https://www.jianshu.com/p/2deca619ff7e
- git概念及工作流程详解
git概念及工作流程详解 既然我们已经把gitlab安装完毕[当然这是非必要条件],我们就可以使用git来管理自己的项目了,前文也多多少少提及到git的基本命令,本文就先简单对比下SVN与git的区别 ...
- Lucene系列六:Lucene搜索详解(Lucene搜索流程详解、搜索核心API详解、基本查询详解、QueryParser详解)
一.搜索流程详解 1. 先看一下Lucene的架构图 由图可知搜索的过程如下: 用户输入搜索的关键字.对关键字进行分词.根据分词结果去索引库里面找到对应的文章id.根据文章id找到对应的文章 2. L ...
- JPEG图像压缩算法流程详解
JPEG图像压缩算法流程详解 JPEG代表Joint Photographic Experts Group(联合图像专家小组).此团队创立于1986年,1992年发布了JPEG的标准而在1994年获得 ...
- unity3d-配置Android环境,打包发布Apk流程详解
31:unity3d-配置Android环境,打包发布Apk流程详解 作者 阿西纳尼 关注 2016.08.28 22:52 字数 498 阅读 1806评论 0喜欢 5 Unity配置Android ...
- linux驱动由浅入深系列:高通sensor架构实例分析之三(adsp上报数据详解、校准流程详解)【转】
本文转载自:https://blog.csdn.net/radianceblau/article/details/76180915 本系列导航: linux驱动由浅入深系列:高通sensor架构实例分 ...
随机推荐
- BZOJ1593 [Usaco2008 Feb]Hotel 旅馆
裸上线段树,就是记的东西有点多... 每个点记区间左端最长0,右端最长0,中间最长0,和tag表示是否全为0/1 直接更新就好,查询的时候先查左儿子,然后查中间,最后查右儿子... /******** ...
- 在Ios里UIWebView参入js
//修改图片大小适应webView宽高度 [webView stringByEvaluatingJavaScriptFromString: @"var sc ...
- lazyload 分页加载
http://www.neoease.com/lazy-load-jquery-plugin-delay-load-image/ echo $d['pic']; ?>" src=&qu ...
- [Js]拖拽
分析: 1.鼠标按下,拖拽开始,鼠标移动,拖拽进行,鼠标抬起,拖拽结束(三个事件) 2.被拖动元素与鼠标之间的位置在拖动过程中始终不变,利用这个原理,被拖动元素的位置就是鼠标的左(上)边距-鼠标与被拖 ...
- ROS程序编辑器
我找到的比较好用的ROS代码编辑器,对于emacs和vim等神级编辑器不能自动补全,对于我这种新手编译出错都是字母打错了, 因此果断回避,找到了一款叫做code blocks的编辑器,在软件中心就能下 ...
- 长理ACM 7-密码破译(闫博钊)
/* //题目标题: *密码破译(闫博钊) //题目描述: *某组织欲破获一个外星人的密码,密码由一定长度的字串组成.此组织拥有一些破译此密码的长度不同的钥匙,若两个钥匙的长度之和恰好为此密码的长度, ...
- HTML--4格式布局
一.position:fixed 锁定位置(相对于浏览器的位置),例如有些网站的右下角的弹出窗口. 示例: 二.position:absolute 1.外层没有position:absolute(或r ...
- FZU1683 矩阵
//Accepted 220 KB 359 ms #include <cstdio> #include <cstring> ; int pp; struct matrix { ...
- LIST 和 MAP
Collection和Map LIST 集合 arraylist arraylist源代码: 1.ArrayList 底层采用数组实现,当使用不带参数的构造方法生成 ArrayList 对象时,实际上 ...
- 安全增强 Linux (SELinux) 剖析
架构和实现 Linux® 一直被认为是最安全的操作系统之一,但是通过引入安全增强 Linux(Security-Enhanced Linux,SELinux),National Security Ag ...