Java并发编程系列之LockSupport的用法
作者:smileNicky 发布时间:2022-04-07 06:48:58
目录
1、什么是LockSupport?
2、两类基本API
3、LockSupport本质
4、LockSupport例子
5、LockSupport源码
总结
1、什么是LockSupport?
LockSupport是用于创建锁和其他同步类的基本线程阻塞原语
2、两类基本API
LockSupport
提供了两类最基本的API:
block线程类:一般都是以pack开头的方法名,pack*(...)
pack方法有两个重载的版本:blocker是一个对象,用于指定阻塞哪个对象。不知道的情况,默认以锁对象自己this为blocker
public static void park();
public static void park(Object blocker);
拓展:parkNanos
函数
public static void parkNanos(Object blocker, long nanos) {
if (nanos > 0) {
// 获取当前线程
Thread t = Thread.currentThread();
// 设置Blocker
setBlocker(t, blocker);
// 获取许可,并设置了时间
UNSAFE.park(false, nanos);
// 设置许可,重新设置blocker为null,避免unpack,获取的blocker为之前设置的
setBlocker(t, null);
}
}
nanos参数表示相对时间,表示等待多长时间
parkUntil
函数:表示在指定的时限前禁用当前线程,deadline参数表示绝对时间,表示指定的时间
public static void parkUntil(Object blocker, long deadline) {
// 获取当前线程
Thread t = Thread.currentThread();
// 设置Blocker
setBlocker(t, blocker);
UNSAFE.park(true, deadline);
// 设置Blocker为null
setBlocker(t, null);
}
unBlock
线程类:unpack(Thread)
unpack方法用于释放许可,指定线程可以继续运行。
3、LockSupport本质
LockSupport是一个许可的信号量机制,pack消费,unpack放入,放入也是仅一个,不累计。例如,调用unpack放入一个信号量,多次调用,这个是不会累计信号量的,pack调用之后会消费
4、LockSupport例子
例子:如何控制两个线程依次打印1、2、3、4、5、6、…
import java.util.concurrent.locks.LockSupport;
public class LockSupportExample {
private static final int total = 10;
private static int i = 0;
static Thread t1 , t2;
public static void main(String[] args) {
t1 = new Thread(() ->{
while (i < total) {
System.out.println("t1:" + (++i));
LockSupport.unpark(t2);
LockSupport.park();
}
});
t2 = new Thread(() -> {
while (i < total) {
LockSupport.park();
System.out.println("t2:" + (++i));
LockSupport.unpark(t1);
}
});
t1.start();
t2.start();
}
}
打印:
t1: 1
t2: 2
t1:3
t2:4
t1:5
t2:6
t1:7
t2:8
t1:9
t2:10
5、LockSupport源码
public class LockSupport {
// Hotspot implementation via intrinsics API
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对象
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); }
}
}
pack方法的源码:
public static void park(Object blocker) {
// 获取当前线程
Thread t = Thread.currentThread();
// 设置Blocker
setBlocker(t, blocker);
// 获取许可
UNSAFE.park(false, 0L);
// 重新可运行后再此设置Blocker为null,避免unpack获取到上一个设置的setBlocker(t, blocker);
setBlocker(t, null);
}
unpack的源码:
public static void unpark(Thread thread) {
if (thread != null) // 线程为不空
UNSAFE.unpark(thread); // 释放该线程许可
}
可以看出,不管是pack的源码还是unpack的源码都是通过Unsafe的底层api实现的
sun.misc.Unsafe
可以直接进行底层非安全操作的工具类
主要提供如下操作:
线程挂起与恢复
CAS操作
操纵对象属性
操纵数组元素
直接操纵内存
总结
本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注脚本之家的更多内容!
来源:https://smilenicky.blog.csdn.net/article/details/121102818


猜你喜欢
- 最近做的项目,需要将一些信息导出到word中。在网上找了好多解决方案,现在将这几天的总结分享一下。目前来看,java导出word大致有6种解
- Eclipse项目中为什么会有红感叹号,具体分析一下【问题原因】:工程中classpath中指向的包路径错误【解决办法】:右键项目名称 Bu
- 如果你是一名Web开发人员,那么用膝盖想也知道你的职业生涯大部分将使用Java而度过。这是一款商业级的编程语言,我们没有办法不接触它。对于J
- 今天遇到pom中添加dependency时相关的jar会自动下载,但是左边的External Libraries中一直获取不到添加的jar问
- 前言Emmmm…最近在做项目的途中,有遇到一个方法需要接收的参数只有一个或者较少的时候就懒得写实体类去接收,使用spr
- RandomAccessFileRandomAccessFile是用来访问那些保存数据记录的文件的,你就可以用seek( )方法来访问记录,
- 前言本文主要介绍了关于java结合keytool实现非对称签名和验证的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍
- 在开发的过程中大家一般都会选择使用数据线连接的方式进行调试,但是有些时候比如使用模拟器时就不能这样了,所以有必要来研究下怎么使用adb通过w
- 新手练手必备~密码账户为:先创建账户类:package cn.Atm;/*** @author 偶my耶*/import java.io.*
- intellij idea是一款非常优秀的软件开发工具,它拥有这强大的插件体系,可以帮助开发者完成很多重量级的功能。今天,我们来学习一下如何
- 一、背景在通过Runnable接口创建线程时,启动线程需要借助Thread类,这里就涉及到了静态代理模式。二、实例以歌手演出为例,在演出的这
- 简单工厂简单工厂模式是属于创建型模式,是工厂模式的一种。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。定义了一个创建对象的类,由
- 获取resources文件路径背景在SpringBoot项目中,需要获取resources文件的路径,网上找了好多文章都不行,后面还是结合官
- 一、问题分析及解决方案1、问题分析上一章我们讲过远程仓储统一管理配置信息,客户端可以通过统一配置服务中心 config server 服务端
- java Swing基础教程之图形化实例代码与多线程、泛型等不同,Swing主要在于使用。 下面主要放代码和注释,少说话。(一)
- 最近项目里面用到了一个日期选择器,实现现在主流的WheelView滑动选择,整理了下,做了个Demo.废话不多说,直接上代码.主布局:act
- 1、0前言最近在学习 Go 语言,Go 语言中有指针对象,一个指针变量指向了一个值的内存地址。学习过 C 语言的猿友应该都知道指针的概念。G
- 前言最近在开发项目的时候涉及到复杂的动态条件查询,但是mybaits本身不支持if elseif类似的判断但是我们可以间接通过 chose
- 前言在日常的测试工作过程中,app可能会出现闪退崩溃的情况,这个时候就需要测试同学快速抓取到崩溃日志,来有效的辅助开发定位问题,快速的去解决
- 本文实例讲解了Android自动提取短信验证码解决方案,分享给大家供大家参考,具体内容如下<uses-permission andro