LockSupport浅析
最初想有没有必要写这类文章,网上相关的文章很多,有些更为透彻,自己再写一篇不免有重复造轮子的感觉。
但想想写文除了分享知识外也可以帮助自己总结归纳,也稍稍可以提高点自我满足感。
基本的线程阻塞原语,被用于创建锁和其他同步类上。
这个类的作用有点类似于Semaphore,通过许可证(permit)来联系使用它的线程。如果许可证可用,调用park方法会立即返回并在这个过程中消费这个许可,不然线程会阻塞。调用unpark会使许可证可用。(和Semaphores有些许区别,许可证不会累加,最多只有一张)
因为有了许可证,所以调用park和unpark的先后关系就不重要了,这里可以对比一下Object的wait和notify,如果先调用同一个对象的notify再wait,那么调用wait的线程依旧会被阻塞,依赖方法的调用顺序。在一些场景下,LockSupport的方法都可以取代notify和wait。举个简单的例子:
final Object lock = new Object();
Thread t1 = new Thread() {
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock) {
lock.notifyAll();
}
};
};
Thread t2 = new Thread() {
public void run() {
synchronized (lock) {
try {
lock.wait();
System.out.println("I am alive");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
};
t1.start();
t2.start();
这段代码,只有确保t2先进入临界区并执行wait后才能正常打印内容。
换成LockSupport就没有这种担心了。
Thread t2 = new Thread() {
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("t2 end sleep");
LockSupport.park(this);
System.out.println("I am alive");
};
};
Thread t1 = new Thread() {
public void run() {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
LockSupport.unpark(t2);
System.out.println("I am done");
};
};
t1.start();
t2.start();
可以先unpark再park,但如API文档所说,unpark需要传入的线程已经启动。在上述t1.start()后用t1.join()等方法在t2启动前调用了unpark就无效了。
但也不意味着wait,notify就没用了。wait是调用对象的方法,和这个对象资源绑定,线程间不需要彼此感知到对方(能获取对方引用),只需要共有这个资源即可,另一方面LockSupport可以指定unpark的线程,这点也是前者无法做到的,两者间不能完全取代彼此。
park方法也有可能在没有"任何理由"的情况下返回,所以通常要在一个循环中使用它并重新判断可以返回的条件。这一点和Object.wait方法一样,可以参考wiki,大致可以理解为底层系统因为优化需要允许出现这样的情况,JVM的线程就是系统线程这种情况也无法避免。可以作为"忙等待"的优化,但是必须要注意要有配对的unpark方法。
使用模式如下:
while (!canProceed()) { ... LockSupport.park(this); }}
在提供的方法中可以看到有一组传入名为blocker对象作为参数的方法,记录这个对象可以方便许可证监视和诊断工具分析。
取上述代码,不启动t1的情况直接运行t2进入阻塞,jstack可以看到:
"Thread-0" #10 prio=5 os_prio=0 tid=0x000000001b586800 nid=0x37f0 waiting on condition [0x000000001c0ae000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000000d603a6e8> (a test.TestLockSupport$1)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at test.TestLockSupport$1.run(TestLockSupport.java:21)
会将传入的对象打出。
更多资料:
https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/locks/LockSupport.html
http://agapple.iteye.com/blog/970055
http://blog.csdn.net/hengyunabc/article/details/28126139
LockSupport浅析的更多相关文章
- 阻塞和唤醒线程——LockSupport功能简介及原理浅析
目录 1.LockSupport功能简介 1.1 使用wait,notify阻塞唤醒线程 1.2 使用LockSupport阻塞唤醒线程 2. LockSupport的其他特色 2.1 可以先唤醒线程 ...
- ReentrantLock和condition源码浅析(二)
转载请注明出处... 接着上一篇的ReentrantLock和condition源码浅析(一),这篇围绕着condition 一.condition的介绍 在这里为了作对比,引入Object类的两个方 ...
- JDK源码那些事儿之浅析Thread上篇
JAVA中多线程的操作对于初学者而言是比较难理解的,其实联想到底层操作系统时我们可能会稍微明白些,对于程序而言最终都是硬件上运行二进制指令,然而,这些又太过底层,今天来看一下JAVA中的线程,浅析JD ...
- 关于 ReentrantLock 中锁 lock() 和解锁 unlock() 的底层原理浅析
关于 ReentrantLock 中锁 lock() 和解锁 unlock() 的底层原理浅析 如下代码,当我们在使用 ReentrantLock 进行加锁和解锁时,底层到底是如何帮助我们进行控制的啦 ...
- SQL Server on Linux 理由浅析
SQL Server on Linux 理由浅析 今天的爆炸性新闻<SQL Server on Linux>基本上在各大科技媒体上刷屏了 大家看到这个新闻都觉得非常震精,而美股,今天微软开 ...
- 【深入浅出jQuery】源码浅析--整体架构
最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...
- 高性能IO模型浅析
高性能IO模型浅析 服务器端编程经常需要构造高性能的IO模型,常见的IO模型有四种: (1)同步阻塞IO(Blocking IO):即传统的IO模型. (2)同步非阻塞IO(Non-blocking ...
- netty5 HTTP协议栈浅析与实践
一.说在前面的话 前段时间,工作上需要做一个针对视频质量的统计分析系统,各端(PC端.移动端和 WEB端)将视频质量数据放在一个 HTTP 请求中上报到服务器,服务器对数据进行解析.分拣后从不同的 ...
- Jvm 内存浅析 及 GC个人学习总结
从诞生至今,20多年过去,Java至今仍是使用最为广泛的语言.这仰赖于Java提供的各种技术和特性,让开发人员能优雅的编写高效的程序.今天我们就来说说Java的一项基本但非常重要的技术内存管理 了解C ...
随机推荐
- 图解Go的channel底层原理
废话不多说,直奔主题. channel的整体结构图 简单说明: buf是有缓冲的channel所特有的结构,用来存储缓存数据.是个循环链表 sendx和recvx用于记录buf这个循环链表中的发送或者 ...
- 实用的JavaScript手册
实用的JavaScript手册,收藏了,需要的时候可以翻阅 包含了 什么是JavaScript: JavaScript基础知识: JavaScript内置对象 JavaScript数据类型的操作方法 ...
- xml代码修改图片颜色
<?xml version="1.0" encoding="utf-8"?> <bitmap xmlns:android="http ...
- web安全系列4:google语法
这是web安全的第四篇,欢迎翻看前面几篇. 前面我们介绍了一些和HTTP有关知识,那么一个疑问就是黑客要做的第一件是什么?其实很简单,确定一个目标,然后搜集信息. 这很容易理解,我们无论做什么都得先有 ...
- 小白的CTF学习之路8——节约内存的编程方式
今天第二更,废话不说上干货 上一章我们学习了内存和cpu间的互动方式,了解到内存的空间非常有限,所以这样就需要我们在编程的时候尽可能的节省内存空间,用最少的空间发挥最大的效果,以下是几种节约内存的方法 ...
- UC浏览器input文本框输入文字回车键自动提交
这是测试今天在jira给我提出的一个bug 下面是贴的代码 屏蔽或者禁止回车键 <!DOCTYPE html> <html> <head> <meta cha ...
- 初学者必看的文章:在VM12中安装 RedHat RHEL7.2 系统的详细步骤:看我如何操纵RHEL系统
一.开始安装 1)新建虚拟机 RHEL7.2 2)成功引导系统--开机出现此画面 Install Red Hat EnterpriseLinux 7.2 安装RHLE7.2 操作系统 Test th ...
- ios系统的Date的兼容问题
内容来源网上,自己记录下 问题1: var date =new Date(); 这个是获取当前系统时间的对象,在各端都可以 但是: var date =new Date("2017-01-2 ...
- cobbler实现系统自动化安装centos
cobbler [epel] cobbler服务集成 PXE DHCP rsync Http DNS Kickstart IPMI[电源管理] 1.软件安装 yum install cobbler d ...
- SJCP认证题前五十题填坑
在做Java的SJCP认证试题时自己整理了一些Java基础细节知识点,以下是知识点陈列 1.标签机制:标签起作用的唯一的地方刚好在迭代语句之前(不然编译错误) continue label1 直接转到 ...