Java并发编程之LockSupport类详解
作者:戏子zzz 发布时间:2022-08-21 10:38:36
标签:Java,LockSupport类,并发编程
一、LockSupport类的属性
private static final sun.misc.Unsafe UNSAFE;
// 表示内存偏移地址
private static final long parkBlockerOffset;
// 表示内存偏移地址
private static final long SEED;
// 表示内存偏移地址
private static final long PROBE;
// 表示内存偏移地址
private static final long SECONDARY;
static {
try {
// 获取Unsafe实例
UNSAFE = sun.misc.Unsafe.getUnsafe();
// 线程类类型
Class<?> tk = Thread.class;
// 获取Thread的parkBlocker字段的内存偏移地址
parkBlockerOffset = UNSAFE.objectFieldOffset(tk.getDeclaredField("parkBlocker"));
// 获取Thread的threadLocalRandomSeed字段的内存偏移地址
SEED = UNSAFE.objectFieldOffset(tk.getDeclaredField("threadLocalRandomSeed"));
// 获取Thread的threadLocalRandomProbe字段的内存偏移地址
PROBE = UNSAFE.objectFieldOffset(tk.getDeclaredField("threadLocalRandomProbe"));
// 获取Thread的threadLocalRandomSecondarySeed字段的内存偏移地址
SECONDARY = UNSAFE.objectFieldOffset(tk.getDeclaredField("threadLocalRandomSecondarySeed"));
} catch (Exception ex) { throw new Error(ex); }
}
二、LockSupport类的构造函数
// 私有构造函数,无法被实例化
private LockSupport() {
}
三、park(Object blocker)方法 和 park()方法分析
//调用park函数时,当前线程首先设置好parkBlocker字段,然后再调用 Unsafe的park函数
// 此后,当前线程就已经阻塞了,等待该线程的unpark函数被调用,所以后面的一个 setBlocker函数无法运行
// unpark函数被调用,该线程获得许可后,就可以继续运行了,也就运行第二个 setBlocker
// 把该线程的parkBlocker字段设置为null,这样就完成了整个park函数的逻辑。
// 总之,必须要保证在park(Object blocker)整个函数 执行完后,该线程的parkBlocker字段又恢复为null。
//阻塞当前线程,并且将当前线程的parkBlocker字段设置为blocker
public static void park(Object blocker) {
// 获取当前线程
Thread t = Thread.currentThread();
//将当前线程的parkBlocker字段设置为blocker
setBlocker(t, blocker);
//阻塞当前线程,第一个参数表示isAbsolute,是否为绝对时间,第二个参数就是代表时间
UNSAFE.park(false, 0L);
//重新可运行后再此设置Blocker
setBlocker(t, null);
}
//无限阻塞线程,直到有其他线程调用unpark方法
public static void park() {
UNSAFE.park(false, 0L);
}
四、parkNanos(Object blocker,long nanos)方法 和 parkNanos(long nanos)方法分析
//阻塞当前线程nanos秒 毫秒
public static void parkNanos(Object blocker, long nanos) {
//先判断nanos是否大于0,小于等于0都代表无限等待
if (nanos > 0) {
// 获取当前线程
Thread t = Thread.currentThread();
//将当前线程的parkBlocker字段设置为blocker
setBlocker(t, blocker);
//阻塞当前线程现对时间的nanos秒
UNSAFE.park(false, nanos);
//将当前线程的parkBlocker字段设置为null
setBlocker(t, null);
}
}
//阻塞当前线程nanos秒 毫秒
public static void parkNanos(long nanos) {
if (nanos > 0)
UNSAFE.park(false, nanos);
}
五、parkUntil(Object blocker,long deadline)方法 和 parkUntil(long deadline)方法分析
//将当前线程阻塞绝对时间的deadline秒,并且将当前线程的parkBlockerOffset设置为blocker
public static void parkUntil(Object blocker, long deadline) {
//获取当前线程
Thread t = Thread.currentThread();
//设置当前线程parkBlocker字段设置为blocker
setBlocker(t, blocker);
//阻塞当前线程绝对时间的deadline秒
UNSAFE.park(true, deadline);
//当前线程parkBlocker字段设置为null
setBlocker(t, null);
}
//将当前线程阻塞绝对时间的deadline秒
public static void parkUntil(long deadline) {
UNSAFE.park(true, deadline);
}
六、setBlocker(Thread t, Object arg)和 getBlocker(Thread t) 方法分析
// 设置线程t的parkBlocker字段的值为arg
private static void setBlocker(Thread t, Object arg) {
UNSAFE.putObject(t, parkBlockerOffset, arg);
}
//获取当前线程的Blocker值
public static Object getBlocker(Thread t) {
//若当前线程为空就抛出异常
if (t == null)
throw new NullPointerException();
//利用unsafe对象获取当前线程的Blocker值
return UNSAFE.getObjectVolatile(t, parkBlockerOffset);
}
七、unpark(Thread thread) 方法分析
//释放该线程的阻塞状态,即类似释放锁,只不过这里是将许可设置为1
public static void unpark(Thread thread) {
// 线程为不空
if (thread != null)
// 释放该线程许可
UNSAFE.unpark(thread);
}
八、LockSupport优点
LockSupport比Object的wait/notify有两大优势
1.LockSupport不需要在同步代码块里 。所以线程间也不需要维护一个共享的同步对象了,实现了线程间的解耦。
2.unpark函数可以先于park调用,所以不需要担心线程间的执行的先后顺序。
来源:https://blog.csdn.net/weixin_45480785/article/details/116721849
0
投稿
猜你喜欢
- 平时我们编写WinForm程序经常使用VS进行拖控件的方式,这样做虽然简单,但是无法深入了解WinForm程序的本质。其实,用记事本也可以编
- 引言本文是关于Spark优化性能与内存使用的最佳实践,翻译整理自Tuning - Spark 3.3.2 Documentation。由于s
- Android ScrollView 下嵌套 ListView 或 GridView出现问题解决办法ScrollView 下嵌套 ListV
- 部署到webapps目录启动本文使用的Spring版本为Spring6,SpringBoot版本为3,JDK为17,可能会和之前有细微不同,
- 编写程序,利用continue语句实现循环体过滤器,过滤“老鹰”字符串,并做相应的处理,但是放弃continue语句之后的所有代码。即若遇到
- 在hibernate5中,有了一些新的变动: 新引导 APISpatial/GIS 支持Java 8 支持扩展 AUTO
- 一、在java中遍历一个文件夹里边的所有文件,可以有两种方式:1.递归遍历,通常也是开发者第一时间能想到的方法,递归遍历的优点是:实现起来相
- 组合模式及其在JDK源码中的运用 前言组合和聚合什么是组合模式示例透明组合模式透明组合模式的缺陷安全组合模式 组合模式角色组合模式在JDK源
- synchronized关键字,一般称之为”同步锁“,用它来修饰需要同步的方法和需要同步代码块,默认是当前对象作为锁的对象。同步锁锁的是同一
- 一.static关键字的用途在《Java编程思想》P86页有这样一段话:“static方法就是没有this的方法。在st
- 本文实例讲述了C#实现缩放和剪裁图片的方法。分享给大家供大家参考,具体如下:using System;using System.Collec
- 最近在做报表统计方面的需求,涉及到行转列报表。根据以往经验使用SQL可以比较容易完成,这次决定挑战一下直接通过代码方式完成行转列。期间遇到几
- 1.情景展示静态方法内部实现:将指定内容生成图片格式的二维码;如何通过多线程实现?2.分析之所以采用多线程,是为了节省时间 3.解
- 在 fluro 中,定义路由处理器 Handler 时可以指定该页面的默认转场形式,或者在使用 navigateTo 方法是可以设置页面跳转
- 本文实例汇总了Java性能优化技巧。分享给大家供大家参考。具体分析如下:这里参考了些书籍,网络资源整理出来,适合于大多数Java应用在JAV
- 一、简介ThreadPool相比Thread来说具备了很多优势,但是ThreadPool却又存在一些使用上的不方便。比如:Task支持线程的
- 一、什么叫做匿名类?匿名类就是没有名字的类。匿名类不能被引用,只能再创建的时候用new语句来声明。二、匿名类的优势以及应用场景;1、匿名类型
- Sentinel 是什么随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统
- 1. 测试文档、期望达到的目标文档效果用于测试的Word文档如下所示,包含的空白段落影响文章整体布局及美观性:目标文档效果:2. 辅助工具2
- 1. 你可以讲下进程与线程的区别?为什么要用多线程?进程:进程是程序的一次执行过程,是系统运行程序的基本单位。线程:单个进程中执行中每个任务