AQS阻塞唤醒工具LockSupport

LockSupport在JDK源码中描述为:构建锁和其他同步类的基本线程阻塞原语,构建更高级别的同步工具集。LockSupport提供的park/unpark从线程的粒度上进行阻塞和唤醒,park/unpark模型真正解耦了线程之间的同步,线程之间不再需要一个Object或者其它变量来存储状态。
本文从阻塞唤醒的语义入手,解释LockSupport的内在机制和注意点,最后与Object的wait和notify做对比,包括以下内容:
- 阻塞和唤醒的语义
- 许可机制
- 底层实现
- 用法
- 与Object的wait和notify区别
阻塞的语义
阻塞是线程在满足某种条件之前暂时停止运行,而被动释放出CPU资源。进入该状态的线程不会主动进入线程队列等待CPU资源,而需要等待满足条件后被唤醒,才能让该线程重新进入到线程队列中排队等待CPU资源。一般造成线程阻塞的原因有:等待获取一个已经被其他线程持有的排他锁、等待某一操作结束、等待某一个时间段。线程阻塞后会被挂起,此时会处于BLOCKED、WAITING、TIMED_WAITING。线程阻塞后会让出CPU资源,这是为避免在自旋上浪费过多的CPU资源,是忙等待(busy wait)的一种优化。
许可机制
LockSupport通过“许可”(permit)机制,使用park/unpark实现线程的阻塞和唤醒。许可是指允许线程继续执行,是线程执行的开关,当开关关闭时,线程会阻塞,当开关打开时,线程会立即执行。
park意指线程在获取许可之前会暂停执行(阻塞在获取许可)。这里的“许可”与线程相关联,类似二元信号量,不可叠加且一个线程只能有一个。有些文章描述“许可”是一次性的,例如当线程A调用park消耗掉一个“许可”(最多只有一个“许可”),在未调用unpark释放出线程A的该“许可”之前,线程A再次调用park时会阻塞在获取“许可”。下文引自Understanding JVM Thread States
there can be only one permit per thread, when thread consumes the permit, it disappears.
出于线程调度的目的,调用park时会阻塞直到许可可用时。如果许可可用,调用park就会立即返回。当前线程就会阻塞,直到调用 unpark 方法,释放出许可。由于许可是默认被占用的,当前线程在启动后调用 park 的话就获取不到许可,因此就进入阻塞状态。
底层实现
LockSupport是使用Unsafe的park实现的,HotSpot Parker用condition和mutex维护了一个_counter变量,park时,变量_counter置为0,unpark时,变量_counter置为1。park操作检查该值是否为1,为1直接返回;不为1,则阻塞。
用法
看到一个关于park/unpark通俗易懂的的例子,代码如下:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
public static void main(String[] args) throws InterruptedException {
Thread threadA = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("周末了我在打游戏");
LockSupport.park();
System.out.println("陪女朋友逛逛街");
}
});
threadA.start();
Thread.sleep(3000);
System.out.println("女朋友准备要喊男朋友逛街");
LockSupport.unpark(threadA);
}
|
在第6行park执行操作时,线程尝试获取许可,由于线程threadA在启动后默认已经获取了许可,park必须等待许可释放后才可以执行。当主线程调用unpark方法释放threadA的许可,threadA才可以继续执行第7行。
与wait和notify区别
park/unpark与wati/notify都提供阻塞唤醒的功能,用做线程间同步,不过两者 的粒度不同,park/unpark作用在线程上,而wait/notify作用在对象上,二者没有交集。Object的wait/notify使用前必须获取对象的监视器,而park/unpark不需要。
写作不易,痛并快乐着;理解可能存在偏差,句句斟酌推敲;抵制抄袭,践行原创技术之路。如果本文能对您有所帮助,实为荣幸,我是葛一凡。
原文
微信公众号
参考
AQS阻塞唤醒工具LockSupport的更多相关文章
- 阻塞和唤醒线程——LockSupport功能简介及原理浅析
目录 1.LockSupport功能简介 1.1 使用wait,notify阻塞唤醒线程 1.2 使用LockSupport阻塞唤醒线程 2. LockSupport的其他特色 2.1 可以先唤醒线程 ...
- java线程阻塞唤醒的四种方式
java在多线程情况下,经常会使用到线程的阻塞与唤醒,这里就为大家简单介绍一下以下几种阻塞/唤醒方式与区别,不做详细的介绍与代码分析 suspend与resume Java废弃 suspend() 去 ...
- Java并发框架——AQS阻塞队列管理(三)——CLH锁改造
在CLH锁核心思想的影响下,Java并发包的基础框架AQS以CLH锁作为基础而设计,其中主要是考虑到CLH锁更容易实现取消与超时功能.比起原来的CLH锁已经做了很大的改造,主要从两方面进行了改造:节点 ...
- 看看AQS阻塞队列和条件队列
上一篇简单介绍了AQS,我们大概知道AQS就是一个框架,把很多功能都给实现了(比如入队规则,唤醒节点中的线程等),我们如果要使用的话只需要实现其中的一些方法(比如tryAcquire等)就行了!这次主 ...
- 多线程同步工具——LockSupport
用例1:子线程等待主线程发放许可! public static void main(String[] args) { Thread thread = new Thread(){ public void ...
- 如何实现Java线程的 阻塞/唤醒(和暂停/继续 类似)
以下为线程 阻塞/唤醒 主要代码 public class MyThread extends Thread { //无意义 private final Object lock = new Objec ...
- 【Java并发编程实战】----- AQS(三):阻塞、唤醒:LockSupport
在上篇博客([Java并发编程实战]----- AQS(二):获取锁.释放锁)中提到,当一个线程加入到CLH队列中时,如果不是头节点是需要判断该节点是否需要挂起:在释放锁后,需要唤醒该线程的继任节点 ...
- Java并发包源码学习系列:挂起与唤醒线程LockSupport工具类
目录 LockSupport概述 park与unpark相关方法 中断演示 blocker的作用 测试无blocker 测试带blocker JDK提供的demo 总结 参考阅读 系列传送门: Jav ...
- 一文带你学会AQS和并发工具类的关系
1. 存在的意义 AQS(AbstractQueuedSynchronizer)是JAVA中众多锁以及并发工具的基础,其底层采用乐观锁,大量使用了CAS操作, 并且在冲突时,采用自旋方式重试,以实 ...
随机推荐
- iOS多线程——GCD与NSOperation总结
很长时间以来,我个人(可能还有很多同学),对多线程编程都存在一些误解.一个很明显的表现是,很多人有这样的看法: 新开一个线程,能提高速度,避免阻塞主线程 毕竟多线程嘛,几个线程一起跑任务,速度快,还不 ...
- We Chall-Training: Crypto - Caesar I-Writeup
MarkdownPad Document html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,ab ...
- W3Cschool学习笔记——XHTML基础教程
XHTML 是更严格更纯净的 HTML 代码. XHTML 是什么? XHTML 指可扩展超文本标签语言(EXtensible HyperText Markup Language). XHTML 的目 ...
- C++编程练习(8)----“二叉树的建立以及二叉树的三种遍历方式“(前序遍历、中序遍历、后续遍历)
树 利用顺序存储和链式存储的特点,可以实现树的存储结构的表示,具体表示法有很多种. 1)双亲表示法:在每个结点中,附设一个指示器指示其双亲结点在数组中的位置. 2)孩子表示法:把每个结点的孩子排列起来 ...
- C++学习的心路历程之心理障碍
断断续续的C++学习已经过了1年多了,可是,我还是没有迈出可以自如输出写点什么的那一步.甚至我因为这个老是怀疑自己的智商,我是真心想学懂,因为这个关系到我的就业,直接关系到我的饭碗.我是十分的着急,可 ...
- 基于Ubuntu14.04-LTS下安装docker
1.sudo apt-get update --更新系统源 2.sudo apt-get install docker.io 3.将docker库的公钥中加入到本地apt中 sudo apt-key ...
- PHP中的 !== 与 !=
'==' 比较两边的值是否相等,会自动转换类型: '===' 则会严格比较类型是否相同,如果类型不相同,直接返回false. 例如:'123' === 123 // => false '!=' ...
- BZOJ 1004: [HNOI2008]Cards(群论)
好吧我就是蒟蒻根本没听说过群论(虽说听叉姐说几万年都不会考) 我也讲不太来,直接戳VFK大神的blog啦 = = http://vfleaking.blog.163.com/blog/static/1 ...
- BZOJ 1606: [Usaco2008 Dec]Hay For Sale 购买干草(动态规划)
裸的背包= =,没什么好说的= = CODE: #include<cstdio>#include<iostream>#include<algorithm>#incl ...
- [译]AngularJS 1.3.0 开发者指南(一) -- 介绍
[译]AngularJS 1.3.0 开发者指南(一) -- 介绍 Angular是什么 ? AngularJS是一款针对动态web应用的结构框架. 它可以让像使用模板语言使用HTML, 并且可以扩展 ...