LockSupport

news/2024/11/13 4:08:21/

LockSupport是一个编程工具类,主要是为了阻塞和唤醒线程用的。使用它我们可以实现很多功能,今天主要就是对这个工具类的讲解,希望对你有帮助:

一、LockSupport简介

1、LockSupport是什么

刚刚开头提到过,LockSupport是一个线程工具类,所有的方法都是静态方法,可以让线程在任意位置阻塞,也可以在任意位置唤醒。

它的内部其实两类主要的方法:park(停车阻塞线程)和unpark(启动唤醒线程)。

注意上面的123方法,都有一个blocker,这个blocker是用来记录线程被阻塞时被谁阻塞的。用于线程监控和分析工具来定位原因的。

现在我们知道了LockSupport是用来阻塞和唤醒线程的,而且之前相信我们都知道wait/notify也是用来阻塞和唤醒线程的,那么它相比,LockSupport有什么优点呢?

2、与wait/notify对比

这里假设你已经了解了wait/notify的机制,如果不了解,可以在网上一搜,很简单。相信你既然学到了这个LockSupport,相信你已经提前已经学了wait/notify。

我们先来举一个使用案例:

上面这段代码的意思是,我们定义一个线程,但是在内部进行了park,因此需要unpark才能唤醒继续执行,不过上面,我们在MyThread进行的park,在main线程进行的unpark。

这样来看,好像和wait/notify没有什么区别。那他的区别到底是什么呢?这个就需要仔细的观察了。这里主要有两点:

(1)wait和notify都是Object中的方法,在调用这两个方法前必须先获得锁对象,但是park不需要获取某个对象的锁就可以锁住线程。

(2)notify只能随机选择一个线程唤醒,无法唤醒指定的线程,unpark却可以唤醒一个指定的线程。

区别就是这俩,还是主要从park和unpark的角度来解释的。既然这个LockSupport这么强,我们就深入一下他的源码看看。

二、源码分析(基于jdk1.8)

1、park方法

blocker是用来记录线程被阻塞时被谁阻塞的。用于线程监控和分析工具来定位原因的。setBlocker(t, blocker)方法的作用是记录t线程是被broker阻塞的。因此我们只关注最核心的方法,也就是UNSAFE.park(false, 0L)。

UNSAFE是一个非常强大的类,他的的操作是基于底层的,也就是可以直接操作内存,因此我们从JVM的角度来分析一下:

每个java线程都有一个Parker实例:

我们换一种角度来理解一下park和unpark,可以想一下,unpark其实就相当于一个许可,告诉特定线程你可以停车,特定线程想要park停车的时候一看到有许可,就可以立马停车继续运行了。因此其执行顺序可以颠倒。

现在有了这个概念,我们体会一下上面JVM层面park的方法,这里面counter字段,就是用来记录所谓的“许可”的。

本文部分总结来源于:https://www.jianshu.com/p/1f16b838ccd8

当调用park时,先尝试直接能否直接拿到“许可”,即_counter>0时,如果成功,则把_counter设置为0,并返回。

如果不成功,则构造一个ThreadBlockInVM,然后检查_counter是不是>0,如果是,则把_counter设置为0,unlock mutex并返回:

否则,再判断等待的时间,然后再调用pthread_cond_wait函数等待,如果等待返回,则把_counter设置为0,unlock mutex并返回:

这就是整个park的过程,总结来说就是消耗“许可”的过程。

2、unpark

还是先来看一下JDK源码:

上面注释的意思是给线程生产许可证。

当unpark时,则简单多了,直接设置_counter为1,再unlock mutext返回。如果_counter之前的值是0,则还要调用pthread_cond_signal唤醒在park中等待的线程:

ok,现在我们已经对源码进行了分析,整个过程其实就是生产许可和消费许可的过程。而且这个生产过程可以反过来。也就是先生产再消费。下面我们使用几个例子验证一波。

三、LockSupport使用

1、先interrupt再park

我们看一下结果:

2、先unpark再park

我们只需在park之前先休眠1秒钟,这样可以确保unpark先执行。

OK,今天的文章先写到这,如有问题,还请批评指正。


http://www.ppmy.cn/news/99728.html

相关文章

115.删除有序数组中的重复项 removeDuplicatesFromSortedArray

文章目录 题目描述解题思路代码详解运行截图 题目描述 题目链接 给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元…

Postman新手教程

博主简介:想进大厂的打工人博主主页:xyk:所属专栏: JavaEE初阶 目录 文章目录 一、Postman背景介绍 二、Postman下载地址 三、Postman简单使用 一、Postman背景介绍 Postman是Chrome插件类产品中的代表产品之一,这款网页调试工具不仅可以调…

数据结构——二叉树

思维导图: 目录 一,什么是二叉树 二 ,二叉树的构建 2.1二叉树的内部结构 2.2手撕二叉树 2.3求二叉树的节点个数 2.3计算二叉树的叶子节点 2.4二叉树的高度 2.5计算第K层有多少个节点 2.6 二叉树的打印 2.6寻找二叉树的节点值 2.7二叉…

嵌入式C语言关键字(const、static、volitatile)

const关键字 C语言中const修饰通常是用来声明常量,并声明常量的值不能修改。当涉及指针变量时情况就会变得更加有趣,需要特别注意。因为有两样东西都有可能成为常量—一种是用来限定指向的空间的值不可修改;另一种是限定指针不可修改。下面是…

牛客HJ43迷宫问题 - 创建智能体通过策略自己找路

文章目录 问题描述思路代码C 问题描述 描述 定义一个二维数组 N*M ,如 5 5 数组下所示: int maze[5][5] { 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, }; 它表示一个迷宫,其中的1表示墙壁&#xff0…

C# | 线性回归算法的实现,只需采集少量数据点,即可拟合整个数据集

C#线性回归算法的实现 文章目录 C#线性回归算法的实现前言示例代码实现思路测试结果结束语 前言 什么是线性回归呢? 简单来说,线性回归是一种用于建立两个变量之间线性关系的统计方法。在我们的软件开发中,线性回归可以应用于数据分析、预测和…

JavaScript 笔记部分导航

看了看也快 50 篇笔记了,稍微整理一下写了点什么,之后复习的时候也方便找内容。 读书笔记 JavaScript 数据可视化编程目录及实例截图 本书开源,地址有在 blog 中分享,这里主要就是放了个目录的思维导图 红宝书系列 也有一些后面…

初阶数据结构之队列的实现(六)

文章目录 😏专栏导读🤖文章导读🙀什么是队列?🙀画图描述 😳队列的代码实现及其各类讲解😳队列实现的理论过程😳队列的初始化代码实现及其讲解😳队列的初始化 &#x1f63…