锁原理剖析-LockSupport工具类

LockSupport工具类

JDK中的rt.jar包里面的LockSupport是个工具类,它的主要作用是挂起和唤醒线程,该工具类是创建锁和其他同步类的基础。

LockSupport类与每个使用它的线程都会关联一个许可证,在默认情况下调用LockSupport类的方法的线程是不持有许可证的。

LockSupport是使用Unsafe类实现的,下面介绍LockSupport中的几个主要函数。

void park()方法

如果调用park方法的线程已经拿到了与LockSupport关联的许可证,则调用LockSupport.park()时会马上返回,否则调用线程会被禁止参与线程的调度,也就是会被阻塞挂起。

如下代码直接在main函数里面调用park方法,最终只会输出begin park!,然后当前线程被挂起,这是因为在默认情况下调用线程是不持有许可证的。

在这里插入图片描述
在其他线程调用unpark(Thread thread)方法并且将当前线程作为参数时,调用park方法而被阻塞的线程会返回。

另外,如果其他线程调用了阻塞线程的interrupt()方法,设置了中断标志或者线程被虚假唤醒,则阻塞线程也会返回。

所以在调用park方法时最好也使用循环条件判断方式。

需要注意的是,因调用park()方法而被阻塞的线程被其他线程中断而返回时并不会抛出InterruptedException异常。

void unpark(Thread thread)方法

当一个线程调用unpark时,如果参数thread线程没有持有thread与LockSupport类关联的许可证,则让thread线程持有。

如果thread之前因调用park()而被挂起,则调用unpark后,该线程会被唤醒。

如果thread之前没有调用park,则调用unpark方法后,再调用park方法,其会立刻返回。

在这里插入图片描述
该代码会输出
在这里插入图片描述
下面再来看一个例子以加深对park和unpark的理解。

在这里插入图片描述该代码会输出
在这里插入图片描述
上面代码首先创建了一个子线程thread,子线程启动后调用park方法,由于在默认情况下子线程没有持有许可证,因而它会把自己挂起。

主线程休眠1s是为了让主线程调用unpark方法前让子线程输出child thread beginpark!并阻塞。

主线程然后执行unpark方法,参数为子线程,这样做的目的是让子线程持有许可证,然后子线程调用的park方法就返回了。

park方法返回时不会告诉你因何种原因返回,所以调用者需要根据之前调用park方法的原因,再次检查条件是否满足,如果不满足则还需要再次调用park方法。

例如,根据调用前后中断状态的对比就可以判断是不是因为被中断才返回的。

为了说明调用park方法后的线程被中断后会返回,我们修改上面的例子代码,删除LockSupport.unpark(thread);,然后添加thread.interrupt();,具体代码如下。

在这里插入图片描述
输出结果为
在这里插入图片描述
你调用unpark(thread)方法子线程也不会结束。

void parkNanos(long nanos)方法

和park方法类似,如果调用park方法的线程已经拿到了与LockSupport关联的许可证,则调用LockSupport.parkNanos(long nanos)方法后会马上返回。

该方法的不同在于,如果没有拿到许可证,则调用线程会被挂起nanos时间后修改为自动返回。

另外park方法还支持带有blocker参数的方法void park(Object blocker)方法,当线程在没有持有许可证的情况下调用park方法而被阻塞挂起时,这个blocker对象会被记录到该线程内部。

使用诊断工具可以观察线程被阻塞的原因,诊断工具是通过调用getBlocker(Thread)方法来获取blocker对象的,所以JDK推荐我们使用带有blocker参数的park方法,并且blocker被设置为this,这样当在打印线程堆栈排查问题时就能知道是哪个类被阻塞了。

在这里插入图片描述

park(Object blocker)方法

在这里插入图片描述
Thread类里面有个变量volatile Object parkBlocker,用来存放park方法传递的blocker对象,也就是把blocker变量存放到了调用park方法的线程的成员变量里面。

void parkNanos(Object blocker,long nanos)方法

相比park(Object blocker)方法多了个超时时间。

void parkUntil(Object blocker,long deadline)方法

在这里插入图片描述
其中参数deadline的时间单位为ms,该时间是从1970年到现在某一个时间点的毫秒值。

这个方法和parkNanos(Object blocker,long nanos)方法的区别是,后者是从当前算等待 nanos秒时间,而前者是指定一个时间点,比如需要等到2017.12.11日 12:00:00,则把这个时间点转换为从1970年到这个时间点的总毫秒数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/302209.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

第2章 JavaScript基本语法

学习目标 了解什么是变量,能够说出变量的概念 掌握变量的命名规则,能够为变量命名 掌握变量的声明与赋值,能够声明变量并为其赋值 熟悉数据类型的分类,能够说出JavaScript中有哪些数据类型 掌握常用的基本数据类型&#xff0c…

【经验分享】如何看论文的分区、SCI检索号、EI检索号等信息

0 前言 一般而言,被SCI检索的论文,都会同时被EI检索。我们以论文《Learning Disentangled Representation for Multimodal Cross-Domain Sentiment Analysis》为例,讲解一下如何查询论文的各项信息。 我们首先百度这个论文 可以看到它是发表…

什么是企业数字化转型?数字化的价值体现在哪里?

从2015年接触平安的数字化转型,到2021年承接阿里云的服务数字化项目,再到2023年主导大大小小10来个数字化项目,8年的时间,数字化对我而言已经从一个“新词”变成了一个“旧词”。 8年过去,数字化也从一道企业的“选做…

轻松学会电脑如何录制音频

随手录音,保留证据以便后续出现问题进行判定,或者保存会议音频记录方便后续根据录音内容整理自己会议记录不足之处等等;越来越多的地方需要用到录音,那么在电脑上该如何进行音频录制呢?特别是使用比较广泛的Windows电脑…

基础算法【解题思路】:单链表的倒数第k个节点

定义指针p1,让p1走k步: 定义指针p2,在p1走了k步的时候,p2也跟着走。 p1走到最后的时候走了n-k步,停留在最后的null结点。 P2从头结点开始,也跟着走到了n-k步,而n-k恰好是倒数第k个节点。 例…

【Axure高保真原型】日期天数加减计算器

今天和大家分享日期天数加减计算器的原型模板,我们通过这个模板选择指定日期,然后填写需要增加或者减少的天数,点击确认按钮后,就可以计算出对应的结束日期,本案例提供中继器版的日期选择器,以及JS版的日期…

mybatisPlus 将List<String>字段转成json字符串,使用JacksonTypeHandler以及自定义类型处理器实现

文章目录 场景使用JacksonTypeHandler实现类型转换自定义StringListTypeHandler处理器实现 场景 项目中经常需要将List转成json存储到配置文件中, mybatisPlus默认实现了JacksonTypeHandler,GsonTypeHandler,FastjsonTypeHandler,也可以自定义…

@Transactional注解的一个很容易被忽略的错误用法

Transactional注解的一个很容易被忽略的错误用法 今日审查代码时发现对Transactional注解的一个如下用法: //StockController.javaAutoWired private StockService stockService//商品出库 PostMapping("/product/stock/out-stock") public Boolean pro…

利用 hexo 搭建 github page

默认我们已经安装了 node.js git 点击就可以下载啦 然后我们在本地新建一个文件夹,我取的名字是Hexo_blog 然后在命令行处输入 或者 右键 点击 git bash here npm install -g hexo-cli 下一步进行Hexo 初始化和本地预览 初始化并安装所需组件: hexo in…

【Linux驱动】Pinctrl子系统 | GPIO子系统 | 基于子系统的LED驱动程序

🐱作者:一只大喵咪1201 🐱专栏:《Linux驱动》 🔥格言:你只管努力,剩下的交给时间! 目录 🛷Pinctrl子系统🥅设备树中的Pinctrl子系统 🛷GPIO子系统…

【漏洞复现】Hikvision SPON IP网络对讲广播系统任意文件上传

漏洞描述 IP网络对讲广播系统是一种基于IP网络的高效、可靠、智能的通信解决方案。它支持全双工语音通信、单呼/多呼、组呼/广播等多种通信模式,可以实现跨地域、跨网络的实时通讯。该系统具有灵活的群组管理、智能化的调度和优先级控制功能,可以满足各种场景下的紧急通讯和…

海外動態IP代理地址在網路連接中的作用

海外動態IP代理地址在確保更安全的流覽體驗方面發揮著重要作用,因為線上隱私和安全是最重要的問題。代理地址充當用戶設備和互聯網之間的仲介,提供多種好處,例如增強隱私、訪問地理限制內容以及提高網路性能等。 本文我們將深入探討一下海外…

如何用UE5 的小白人替换成自己的 metahumen 数字人

1、用QuixelBridge 插件导入制作好的metahumen数字人 2、创建项目时如有选择第三人称游戏,在内容目录中找到第三人称游戏小白人的蓝图类,对其进行复制一个,重命名,我这里命名为BP_METAHUMEN, 并移到Metahumen目录下方便…

番外篇-Julius AI帮你做数据分析

今天咱们聊聊如何利用AI大模型来做数据分析,非常适合小白体验,尤其是缺乏项目经验的同学,强烈建议关注收藏,也欢迎私信交流~ 1. 站在巨人肩膀 在数据分析领域,AI技术的飞速发展正引领一场革命。随着大型机器学习模型…

C++设计模式 --1.工厂模式和单例模式

文章目录 1.工厂模式简单工厂模式工厂方法模式抽象工厂模式 2.单例模式懒汉式饿汉式 1.工厂模式 简单工厂模式 抽象产品类 //定义一个抽象水果类 --抽象产品角色 class AbstractFruit { public:virtual void showFruitName()0;//抽取出产品的公共行为, 纯虚函数v…

轻量级VS Code运行HTML代码不是难事,这里提供几个方法

对于那些刚开始编码的人来说,Visual Studio Code(VS Code)是更大、更复杂的代码编辑器的一个很好的替代品。特别是对于网络开发人员来说,它提供了许多编写和调整HTML部分的机会,加上大量的功能,使开发成为一次激动人心的旅程。 但是,如果你是开发界的新手,那么你究竟是…

Vue3-37-路由-组件内的路由守卫 onBeforeRouteLeave 和 onBeforeRouteUpdate

简介 组件内的路由守卫,实际上就是两个 API 方法。 他们与普通的守卫不同的是 : 他们是写在组件内的,在组件中监听路由的变化,不是全局的,比较灵活。 以下是两个 API 的功能说明:onBeforeRouteLeave() : 守…

SpringBoot项目如何防止反编译?

SpringBoot项目如何防止反编译? 场景方案项目操作启动方式反编译效果绑定机器启动 场景 最近项目要求部署到其他公司的服务器上,但是又不想将源码泄露出去。要求对正式环境的启动包进行安全性处理,防止客户直接通过反编译工具将代码反编译出…

x-cmd pkg | busybox - 嵌入式 Linux 的瑞士军刀

目录 简介首次用户功能特点竞品和相关作品 进一步阅读 简介 busybox 是一个开源的轻量级工具集合,集成了一批最常用 Unix 工具命令,只需要几 MB 大小就能覆盖绝大多数用户在 Linux 的使用,能在多款 POSIX 环境的操作系统(如 Linu…

二叉树题目:好叶子结点对的数量

文章目录 题目标题和出处难度题目描述要求示例数据范围 解法思路和算法代码复杂度分析 题目 标题和出处 标题:好叶子结点对的数量 出处:1530. 好叶子结点对的数量 难度 6 级 题目描述 要求 给定二叉树的根结点 root \texttt{root} root 和整数 …