LockSupport的深入浅出
public static void main(String[] args)throws Exception {
final Object obj = new Object();
Thread A = new Thread(new Runnable() {
@Override
public void run() {
int sum = 0;
for(int i=0;i<10;i++){
sum+=i;
}
try {
synchronized (obj){
obj.wait();
}
}catch (Exception e){
e.printStackTrace();
}
System.out.println(sum);
}
});
A.start();
//睡眠一秒钟,保证线程A已经计算完成,阻塞在wait方法
//Thread.sleep(1000);
synchronized (obj){
obj.notify();
}
}
LockSupport是JDK中比较底层的类,用来创建锁和其他同步工具类的基本线程阻塞原语。java锁和同步器框架的核心AQS:AbstractQueuedSynchronizer,就是通过调用LockSupport.park()和LockSupport.unpark()实现线程的阻塞和唤醒的。LockSupport很类似于二元信号量(只有1个许可证可供使用),如果这个许可还没有被占用,当前线程获取许可并继续执行;如果许可已经被占用,当前线程阻塞,等待获取许可
permit相当于1,0的开关,默认是0,调用一次unpark就加1变成1,调用一次park会消费permit, 也就是将1变成0,同时park立即返回。再次调用park会变成block(因为permit为0了,会阻塞在这里,直到permit变为1), 这时调用unpark会把permit置为1。每个线程都有一个相关的permit, permit最多只有一个,重复调用unpark也不会积累。
LockSupport函数列表
// 返回提供给最近一次尚未解除阻塞的 park 方法调用的 blocker 对象,如果该调用不受阻塞,则返回 null。
static Object getBlocker(Thread t)
// 为了线程调度,禁用当前线程,除非许可可用。
static void park()
// 为了线程调度,在许可可用之前禁用当前线程。
static void park(Object blocker)
// 为了线程调度禁用当前线程,最多等待指定的等待时间,除非许可可用。
static void parkNanos(long nanos)
// 为了线程调度,在许可可用前禁用当前线程,并最多等待指定的等待时间。
static void parkNanos(Object blocker, long nanos)
// 为了线程调度,在指定的时限前禁用当前线程,除非许可可用。
static void parkUntil(long deadline)
// 为了线程调度,在指定的时限前禁用当前线程,除非许可可用。
static void parkUntil(Object blocker, long deadline)
// 如果给定线程的许可尚不可用,则使其可用。
static void unpark(Thread thread)
说明:LockSupport是通过调用Unsafe函数中的接口实现阻塞和解除阻塞的。
下面是unpark的英文
Makes available the permit for the given thread, if it was not already available. If the thread was blocked on park then it will unblock. Otherwise, its next call to park is guaranteed not to block. This operation is not guaranteed to have any effect at all if the given thread has not been started.
使给定线程的许可证可用(如果它还没有可用)。如果线程在park上被阻塞,那么它将解阻塞。否则,它下次调用park时,保证不会阻塞。如果没有启动给定的线程,则不能保证此操作具有任何效果。
下面是park的英文
Disables the current thread for thread scheduling purposes unless the permit is available.
If the permit is available then it is consumed and the call returns immediately; otherwise the current thread becomes disabled for thread scheduling purposes and lies dormant until one of three things happens:
Some other thread invokes unpark with the current thread as the target; or
Some other thread interrupts the current thread; or
The call spuriously (that is, for no reason) returns.
This method does not report which of these caused the method to return. Callers should re-check the conditions which caused the thread to park in the first place. Callers may also determine, for example, the interrupt status of the thread upon return.
除非有许可证,否则为线程调度目的禁用当前线程。【也就是说默认任何线程调用都会被阻塞,因为没有对应许可证,只有调用完unpark分配给线程许可证,才可以执行任务】
如果许可证是可用的,那么它将被使用,调用立即返回;否则,当前线程将出于线程调度的目的被禁用,并处于休眠状态,直到以下三种情况之一发生:
其他一些线程以当前线程为目标调用unpark;或
其他一些线程中断当前线程;或
虚假的调用(也就是说,没有理由)返回。
此方法不报告是哪些原因导致该方法返回。调用者应该重新检查导致线程首先停车的条件。例如,调用者还可以在返回时确定线程的中断状态。
先看上面那段代码 用notify wait来阻塞和唤醒线程 有几个弊端 首先加入notify wait的代码都需要内置锁 还有就是不能保证顺序 像上面那段代码有可能主线程先调用notify然后wait就一直阻塞了
public class TestObjWait {
public static void main(String[] args)throws Exception {
final Object obj = new Object();
Thread A = new Thread(new Runnable() {
@Override
public void run() {
int sum = 0;
for(int i=0;i<10;i++){
sum+=i;
}
LockSupport.park();
System.out.println(sum);
}
});
A.start();
//睡眠一秒钟,保证线程A已经计算完成,阻塞在wait方法
//Thread.sleep(1000);
LockSupport.unpark(A);
}
}像上面这段代码 无论执行多少次 结果都能准确输出。
总结一下,LockSupport比Object的wait/notify有两大优势:
①LockSupport不需要在同步代码块里 。所以线程间也不需要维护一个共享的同步对象了,实现了线程间的解耦。
②unpark函数可以先于park调用,所以不需要担心线程间的执行的先后顺序。
LockSupport的深入浅出的更多相关文章
- 自己动手写把”锁”---LockSupport深入浅出
本篇是<自己动手写把"锁">系列技术铺垫的最后一个知识点.本篇主要讲解LockSupport工具类,它用来实现线程的挂起和唤醒. LockSupport是Java6引入 ...
- 【转】LockSupport深入浅出
原文:https://www.cnblogs.com/qingquanzi/p/8228422.html 本篇是<自己动手写把"锁">系列技术铺垫的最后一个知识点.本篇 ...
- ”锁“-LockSupport深入浅出
LockSupport是Java6引入的一个工具类,它简单灵活,应用广泛. 一.简单 俗话说,没有比较就没有伤害.这里咱们还是通过对比来介绍LockSupport的简单. 在没有LockSupport ...
- 深入浅出Java并发包—锁机制(三)
接上文<深入浅出Java并发包—锁机制(二)> 由锁衍生的下一个对象是条件变量,这个对象的存在很大程度上是为了解决Object.wait/notify/notifyAll难以使用的问题. ...
- 深入浅出Java并发包—锁机制(二)
接上文<深入浅出Java并发包—锁机制(一) > 2.Sync.FairSync.TryAcquire(公平锁) 我们直接来看代码 protected final boolean tr ...
- 深入浅出AQS之条件队列
相比于独占锁跟共享锁,AbstractQueuedSynchronizer中的条件队列可能被关注的并不是很多,但它在阻塞队列的实现里起着至关重要的作用,同时如果想全面了解AQS,条件队列也是必须要学习 ...
- 深入浅出多线程——ReentrantLock (二)
深入浅出多线程——ReentrantLock (一)文章中介绍了该类的基本使用,以及在源码的角度分析lock().unlock()方法.这次打算在此基础上介绍另一个极为重要的方法newConditio ...
- Java并发实现线程阻塞原语LockSupport
LockSupport 和 CAS 是Java并发包中很多并发工具控制机制的基础,它们底层其实都是依赖Unsafe实现.LockSupport是用来创建锁和其他同步类的基本线程阻塞原语. 1.Lock ...
- 深入浅出ReentrantReadWriteLock源码解析
读写锁实现逻辑相对比较复杂,但是却是一个经常使用到的功能,希望将我对ReentrantReadWriteLock的源码的理解记录下来,可以对大家有帮助 前提条件 在理解ReentrantReadWri ...
随机推荐
- keeplived高可用集群
什么是Keeplived? Keepalived是Linux下面实现VRRP备份路由的高可靠性运行件.基于Keepalived设计的服务模式能够真正做到主服务器和备份服务器故障时IP瞬间无缝交接.二者 ...
- Python中容器指的是什么?
容器:容器是一种把多个元素组织在一起的数据结构,容器中的元素可以逐个地迭代获取,可以用in, not in关键字判断元素是否包含在容器中. 容器是一种可以包含其他类型对象(如列表.元组.字典等)作为元 ...
- 【Alpha冲刺阶段】Scrum Meeting Daily1
1.会议简述 会议开展时间 2020/5/22 8:30-9:00 PM 会议基本内容摘要 讨论了基础的分工,以及明确了各自模块需要完成的任务 参与讨论人员 全体参与 特别说明 会议需要每天都开展!! ...
- Markdown 公式指导手册
本文为 Markdown 环境下的常用语法指引.Typora 编辑阅读器支持 \(\LaTeX\) 编辑显示支持,例如:\(\sum_{i=1}^n a_i=0\),访问 MathJax 以参考更多使 ...
- AcWing 330. 估算
大型补档计划 题目链接 若 \(K = 1\),显然,\(B[i]\) 取 \(A\) 序列的中位数时最优. 考虑扩展,我们只需要把 \(A\) 分成 \(K\) 段,每段内, \(B\) 最优的取值 ...
- gnuplot添加直线和箭头
http://blog.csdn.net/bill_chuang/article/details/18215051 6.在图中添加直线和箭头 gnuplot> set arrow from 0. ...
- ERROR 1071 (42000): Specified key was too long; max key length is 1000 bytes
这个错误是我在安装ambari平台时,准备为ambari指定mysql数据库时,执行建表语句时遇到的. ERROR 1071 (42000): Specified key was too long; ...
- 群晖DS218+部署Harbor(1.10.3)
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- DVWA-文件包含-目录遍历学习笔记
参考文献资料: https://www.cnblogs.com/s0ky1xd/p/5823685.html https://www.cnblogs.com/yuzly/p/10799486.html ...
- 持久层之 MyBatis: 第三篇 :缓存 And 高级查询
MyBatis入门到精通3 缓存机制 Mybatis一级缓存测试 Mybatis二级缓存测试 高级查询 表关系说明 一对一查询 一对多查询 多对多查询 缓存机制 正如大多数持久层框架一样,MyBati ...