当前位置: 首页 > news >正文

LockSupport常用方法源码分析

前言:本文将介绍LockSupport类中的方法和部分源码,以及面试常问到的一个小问题,感兴趣的大佬可以指点下。
希望能够加深自己的印象以及帮助到其他的小伙伴儿们😉😉。
如果文章有什么需要改进的地方还请大佬不吝赐教👏👏。
小威在此先感谢各位大佬啦~~🤞🤞

在这里插入图片描述

🏠个人主页:小威要向诸佬学习呀
🧑个人简介:大家好,我是小威,一个想要与大家共同进步的男人😉😉
目前状况🎉:24届毕业生,曾经在某央企公司实习,目前在某税务公司实习👏👏

💕欢迎大家:这里是CSDN,我总结知识的地方,欢迎来到我的博客,我亲爱的大佬😘

以下正文开始
在这里插入图片描述

LockSupport类常用方法源码

LockSupport只是一个简单的基础类,位于java.util.concurrent.locks包下,多用于线程的阻塞和唤醒,因此LockSupport也被称为其他线程的工具类。
LockSupport类的源码有标注,LockSupport类无法实例化。LockSupport类的底层是有Unsafe类实现的,LockSupport加载时的初始化也用到了Unsafe获取成员的偏移量,其源码如下:

    // Hotspot implementation via intrinsics APIprivate 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 = sun.misc.Unsafe.getUnsafe();Class<?> tk = Thread.class;parkBlockerOffset = UNSAFE.objectFieldOffset(tk.getDeclaredField("parkBlocker"));SEED = UNSAFE.objectFieldOffset(tk.getDeclaredField("threadLocalRandomSeed"));PROBE = UNSAFE.objectFieldOffset(tk.getDeclaredField("threadLocalRandomProbe"));SECONDARY = UNSAFE.objectFieldOffset(tk.getDeclaredField("threadLocalRandomSecondarySeed"));} catch (Exception ex) { throw new Error(ex); }}

LockSupport类中有一些核心的线程操作方法,多用于线程的阻塞与唤醒。
调用park()方法使线程阻塞:

    public static void park(Object blocker) {Thread t = Thread.currentThread();setBlocker(t, blocker);UNSAFE.park(false, 0L);setBlocker(t, null);}private static void setBlocker(Thread t, Object arg) {// Even though volatile, hotspot doesn't need a write barrier here.UNSAFE.putObject(t, parkBlockerOffset, arg);}

调用park(Object blocker)对传入的线程进行阻塞

    public static void park(Object blocker) {Thread t = Thread.currentThread();setBlocker(t, blocker);UNSAFE.park(false, 0L);setBlocker(t, null);}

在截止时间之前阻塞传入的某个线程:

    public static void parkUntil(Object blocker, long deadline) {Thread t = Thread.currentThread();setBlocker(t, blocker);UNSAFE.park(true, deadline);setBlocker(t, null);}

在nanos的时间范围内阻塞传入的线程:

    public static void parkNanos(Object blocker, long nanos) {if (nanos > 0) {Thread t = Thread.currentThread();setBlocker(t, blocker);UNSAFE.park(false, nanos);setBlocker(t, null);}}

唤醒传入的线程:

    public static void unpark(Thread thread) {if (thread != null)UNSAFE.unpark(thread);}

在这里插入图片描述

wait/notify方法和park/unpark方法区别

LockSupport类中的方法还有很多,在此先列举到这里。当我们看到阻塞和唤醒方法时,我们会联想到另一组唤醒方法wait()和notify(),这两组方法还是有所区别的。
这里直接记录下结论:wait和notify方法只能在同步代码块中使用(即必须与synchronized连用);必须先执行wait方法,然后再执行notify方法唤醒线程,调换顺序的话线程仍处于阻塞状态。

而park()和unpark()方法与之不同,这里可以通过代码运行结果来看:

package XIAOWEI;
import java.util.concurrent.locks.LockSupport;public class Xiaowei{public static void main(String[] args) {Thread A = new Thread(()-> {System.out.println("线程A已经被阻塞QWQ");LockSupport.park();System.out.println("线程A被线程B唤醒啦~~~");});A.start();new Thread(()->{System.out.println("线程B在唤醒线程A ing~~~");LockSupport.unpark(A);},"B").start();}
}

在这里插入图片描述
那如果我们先通过线程B唤醒线程A,然后再让线程A阻塞呢(让线程A的阻塞休眠两秒)?

package XIAOWEI;
import java.util.concurrent.locks.LockSupport;
public class Xiaowei {public static void main(String[] args) {Thread A = new Thread(()-> {try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("线程A已经被阻塞QWQ(第二版)");LockSupport.park();System.out.println("线程A被线程B唤醒啦~~~(第二版)");});A.start();new Thread(()->{System.out.println("线程B在唤醒线程A ing~~~驾驾驾");LockSupport.unpark(A);},"B").start();}
}

在这里插入图片描述
由上面输出结果来看,虽然线程B先唤醒了线程A,然后线程A再开始阻塞,但是线程A还是处于唤醒状态,这是为什么呢?

接下来我找了段LockSupport类中的注释,其实有时看看注释也挺有意思的哈哈:

 * <p>This class associates, with each thread that uses it, a permit* (in the sense of the {@link java.util.concurrent.Semaphore* Semaphore} class). A call to {@code park} will return immediately* if the permit is available, consuming it in the process; otherwise* it <em>may</em> block.  A call to {@code unpark} makes the permit* available, if it was not already available. (Unlike with Semaphores* though, permits do not accumulate. There is at most one.)

这段话大意是说,LockSupport类使用permits这个东西来实现线程的阻塞和唤醒。每一个线程都会使用到(拥有)permit,且permit的值默认为0。接着它又说,这个概念和Semaphore信号量差不多,但是permit的值只有0和1两个值。哦~原来是这样。

对于上面例子,线程B调用unpark方法唤醒A后,会使得线程A的permit值为1,当线程调用park方法使自己阻塞时,发现自己已经有许可(permit)了,就会继续向下执行业务,而不会阻塞不动。
在这里插入图片描述

好了,本篇文章就先分享到这里了,后续会继续分享其他方面的知识,感谢大佬认真读完支持咯~
在这里插入图片描述

文章到这里就结束了,如果有什么疑问的地方请指出,诸佬们一起讨论😁
希望能和诸佬们一起努力,今后我们顶峰相见🍻
再次感谢各位小伙伴儿们的支持🤞

在这里插入图片描述

相关文章:

LockSupport常用方法源码分析

前言&#xff1a;本文将介绍LockSupport类中的方法和部分源码&#xff0c;以及面试常问到的一个小问题&#xff0c;感兴趣的大佬可以指点下。 希望能够加深自己的印象以及帮助到其他的小伙伴儿们&#x1f609;&#x1f609;。 如果文章有什么需要改进的地方还请大佬不吝赐教&am…...

Mybatis Notes

文章目录1 Mybatis 介绍1.1 快速入门2 JDBC2.1 JDBC介绍2.3 JDBC问题分析2.4 Mybatis与JDBC技术对比3 数据库连接池3.1 数据库连接池介绍3.2 数据库连接池产品产品3.3 Druid引入项目4lombok4.1 lombok介绍4.2 lombok使用4.2.1 在pom.xml文件中引入依赖4.2.2 pojo类代码引入1 My…...

MySQL 10:MySQL事务

MySQL 中的事务是由存储引擎实现的。在 MySQL 中&#xff0c;只有 InnoDB 存储引擎支持事务。事务处理可用于维护数据库的完整性&#xff0c;确保批处理的 SQL 语句要么执行要么根本不执行。事务用于管理 DDL、DML 和 DCL 操作&#xff0c;例如插入、更新和删除语句&#xff0c…...

软件设计(十三)-原码、反码、补码、移码

软件设计&#xff08;十二&#xff09;数据结构(下)https://blog.csdn.net/ke1ying/article/details/129035300 下面把一个数转成二进制表达形式 原码&#xff1a; 数值1 &#xff1a; 0000 0001 数值-1 &#xff1a; 1000 0001 1 (- 1) &#xff1a; 1000 0010 这是8个…...

5.4 BGP地址聚合

5.3.1配置BGP地址聚合 1. 实验目的 熟悉BGP地址聚合的应用场景掌握BGP地址聚合的配置方法2. 实验拓扑 实验拓扑如图5-4所示: 图5-4:配置BGP地址聚合 3. 实验步骤 (1)配置IP地址 R1的配置 <Huawe…...

华为OD机试 - 数列还原(Python) | 机试题算法思路 【2023】

最近更新的博客 华为OD机试 - 自动曝光(Python) | 机试题算法思路 【2023】 华为OD机试 - 双十一(Python) | 机试题算法思路 【2023】 华为OD机试 - 删除最少字符(Python) | 机试题算法思路 【2023-02】 华为OD机试 - Excel 单元格数值统计(Python) | 机试题算法思路 …...

华为OD机试题 - 新工号系统(JavaScript)| 代码+思路+重要知识点

最近更新的博客 华为OD机试题 - 字符串加密(JavaScript) 华为OD机试题 - 字母消消乐(JavaScript) 华为OD机试题 - 字母计数(JavaScript) 华为OD机试题 - 整数分解(JavaScript) 华为OD机试题 - 单词反转(JavaScript) 使用说明 参加华为od机试,一定要注意不要完全背…...

Java-算法竞赛中常用的Java API之大数类

Java-算法竞赛中常用的Java API之大数类摘要BigInteger和BigDecimal创建赋值加法减法乘法除法*取余*求最大公因数求最值*(a^b)%mod比较大小*进制转化类型转化BigDecimal精度问题保留n位小数摘要 java中的基础数据类型能存储的最大的二进制数是 2 ^ 63 - 1, 对应的十进制数是92…...

了解Nginx,这一篇就够了

了解Nginx&#xff0c;这一篇就够了1.Nginx应用场景2.Nginx相关概念正向代理和反向代理负载均衡动静分离3.Nginx配置文件解析全局块events块http块1.Nginx应用场景 HTTP服务器&#xff1a;Nginx本身也是一个静态资源的服务器&#xff0c;当只有静态资源的时候&#xff0c;就可…...

k8s删除pod或deployment

查看pod或者deployment信息 deployment&#xff1a; kubectl get deployment -n 命名空间pod&#xff1a; kubectl get pod -n 命名空间删除pod或者deployment 删除pod&#xff1a; kubectl delete pod <pod名> -n <命名空间>可是&#xff0c;此时你会发现刚刚…...

Visual Studio 2022: 增加对虚幻引擎的支持

自 Visual Studio 2022 发布以来&#xff0c;我们一直专注于为游戏和大型项目开发人员提供一系列生产力和性能改进。今天&#xff0c;我们很高兴与大家分享下一组专门用来提高虚幻引擎开发效率的功能。我们听到并看到了来自你&#xff08;我们的游戏开发人员&#xff09;的大量…...

【Python】以邮件的方式定时发送一天的股票分析报告

【Python】以邮件的方式定时发送一天的股票分析报告 文章目录【Python】以邮件的方式定时发送一天的股票分析报告1、Python发送邮件1&#xff09;EmailSender封装2&#xff09;可能存在的问题2、jinja2动态渲染html页面3、阿里云OSS搭建图床1&#xff09;Python上传图片到OSS中…...

mybatis条件构造器(二)

mybatis条件构造器(二) 1 准备工作 1.1 建表sql语句(Emp表) SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS 0;-- ---------------------------- -- Table structure for emp -- ---------------------------- DROP TABLE IF EXISTS emp; CREATE TABLE emp (EMPNO int NOT NU…...

C++【类与对象】

文章目录类与对象&#xff08;1&#xff09;类与对象一1.0.面向过程和面向对象初步认识1.1.类的引入1.2.类的定义1.3.类的访问限定符及封装1.4.类的作用域1.5.类的实例化1.6.类的对象大小的计算1.8.类成员函数的this指针&#xff08;2&#xff09;类与对象二2.0类的6个默认成员…...

假设检验选择统计量重点-----正态总体参数的假设检验

文章目录单个正态总体参数的假设检验单个正态总体N(μ,σ2)N(\mu,\sigma^2)N(μ,σ2)的均值μ\muμ的假设检验1.σ2\sigma^2σ2已知(U检验法)单个正态总体方差的假设检验单边检验简介--计算拒绝域两个正态总体参数的假设检验方差已知的两正态总体均值的假设检验均值未知的两正态…...

华为OD机试 - 通信误码(Python) | 机试题算法思路 【2023】

最近更新的博客 华为OD机试 - 自动曝光(Python) | 机试题算法思路 【2023】 华为OD机试 - 双十一(Python) | 机试题算法思路 【2023】 华为OD机试 - 删除最少字符(Python) | 机试题算法思路 【2023-02】 华为OD机试 - Excel 单元格数值统计(Python) | 机试题算法思路 …...

设计模式之装饰者模式

文章の目录一、什么是装饰者模式二、优势三、缺点四、应用场景五、示例参考写在最后一、什么是装饰者模式 装饰者模式也称为包装器模式&#xff0c;在不改变原有对象的基础上为其动态的添加上新的功能。 装饰者模式有以下特点&#xff1a; 添加功能时不改变原对象结构。装饰…...

【第31天】SQL进阶-写优化- 插入优化(SQL 小虚竹)

回城传送–》《31天SQL筑基》 文章目录零、前言一、练习题目二、SQL思路&#xff1a;SQL进阶-写优化-插入优化解法插入优化禁用索引语法如下适用数据库引擎非空表&#xff1a;禁用索引禁用唯一性检查语法如下适用数据库引擎禁用外键检查语法如下适用数据库引擎批量插入数据语法…...

SpringBoot自动装配的原理

前言 在开发SpringBoot项目时&#xff0c;当我们引入spring-boot-starter-xxx依赖后&#xff0c;想要使用依赖中的bean&#xff0c;直接就用Autowired拿来用了&#xff0c;不需要用xml或者注解的方式把它先注入到Spring容器中。这就是自动装配的特性&#xff0c;本文来讲述Spri…...

Vue3电商项目实战-分类模块5【12-二级类目-结果区-排序组件、13-二级类目-结果区-数据加载、14-二级类目-结果区-进行筛选】

文章目录12-二级类目-结果区-排序组件13-二级类目-结果区-数据加载14-二级类目-结果区-进行筛选12-二级类目-结果区-排序组件 目的&#xff1a;封装排序组件&#xff0c;完成排序切换效果 大致步骤&#xff1a; 定义一个组件 sub-sort&#xff0c;完成基础布局在 sub.vue 组件…...

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站&#xff0c;会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后&#xff0c;网站没有变化的情况。 不熟悉siteground主机的新手&#xff0c;遇到这个问题&#xff0c;就很抓狂&#xff0c;明明是哪都没操作错误&#x…...

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇&#xff0c;在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下&#xff1a; 【Note】&#xff1a;如果你已经完成安装等操作&#xff0c;可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作&#xff0c;重…...

内存分配函数malloc kmalloc vmalloc

内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...

在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:

在 HarmonyOS 应用开发中&#xff0c;手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力&#xff0c;既支持点击、长按、拖拽等基础单一手势的精细控制&#xff0c;也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档&#xff0c…...

拉力测试cuda pytorch 把 4070显卡拉满

import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试&#xff0c;通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小&#xff0c;增大可提高计算复杂度duration: 测试持续时间&#xff08;秒&…...

C# SqlSugar:依赖注入与仓储模式实践

C# SqlSugar&#xff1a;依赖注入与仓储模式实践 在 C# 的应用开发中&#xff0c;数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护&#xff0c;许多开发者会选择成熟的 ORM&#xff08;对象关系映射&#xff09;框架&#xff0c;SqlSugar 就是其中备受…...

SpringCloudGateway 自定义局部过滤器

场景&#xff1a; 将所有请求转化为同一路径请求&#xff08;方便穿网配置&#xff09;在请求头内标识原来路径&#xff0c;然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...

浅谈不同二分算法的查找情况

二分算法原理比较简单&#xff0c;但是实际的算法模板却有很多&#xff0c;这一切都源于二分查找问题中的复杂情况和二分算法的边界处理&#xff0c;以下是博主对一些二分算法查找的情况分析。 需要说明的是&#xff0c;以下二分算法都是基于有序序列为升序有序的情况&#xf…...

CMake控制VS2022项目文件分组

我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...

是否存在路径(FIFOBB算法)

题目描述 一个具有 n 个顶点e条边的无向图&#xff0c;该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序&#xff0c;确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数&#xff0c;分别表示n 和 e 的值&#xff08;1…...