Java多线程:ReentrantLock中的方法
公平锁与非公平锁
ReentrantLock有一个很大的特点,就是可以指定锁是公平锁还是非公平锁,公平锁表示线程获取锁的顺序是按照线程排队的顺序来分配的,而非公平锁就是一种获取锁的抢占机制,是随机获得锁的,先来的未必就一定能先得到锁,从这个角度讲,synchronized其实就是一种非公平锁。非公平锁的方式可能造成某些线程一直拿不到锁,自然是非公平的了。看一下例子,new ReentrantLock的时候有一个单一参数的构造函数表示构造的是一个公平锁还是非公平锁,传入true就可以了:
public class ThreadDomain42 {private Lock lock = new ReentrantLock(true);public void testMethod() {try {lock.lock();System.out.println("ThreadName" + Thread.currentThread().getName() + "获得锁");} finally {lock.unlock();}}}public static void main(String[] args) throws Exception {final ThreadDomain42 td = new ThreadDomain42();Runnable runnable = new Runnable() {public void run() {System.out.println("◆线程" + Thread.currentThread().getName() + "运行了");td.testMethod();}};Thread[] threads = new Thread[5];for (int i = 0; i < 5; i++)threads[i] = new Thread(runnable);for (int i = 0; i < 5; i++)threads[i].start();}
看一下运行结果:
◆线程Thread-0运行了
◆线程Thread-3运行了
ThreadNameThread-0获得锁
◆线程Thread-2运行了
◆线程Thread-1运行了
ThreadNameThread-3获得锁
◆线程Thread-4运行了
ThreadNameThread-2获得锁
ThreadNameThread-1获得锁
ThreadNameThread-4获得锁
我们的代码很简单,一执行run()方法的第一步就是尝试获得锁。看到结果里面获得锁的顺序和线程启动顺序是一致的,这就是公平锁。对比一下,如果是非公平锁运行结果是怎么样的,在new ReentrantLock的时候传入false:
◆线程Thread-1运行了
◆线程Thread-2运行了
◆线程Thread-0运行了
ThreadNameThread-1获得锁
ThreadNameThread-2获得锁
◆线程Thread-3运行了
◆线程Thread-4运行了
ThreadNameThread-3获得锁
ThreadNameThread-0获得锁
ThreadNameThread-4获得锁
线程启动顺序是1 2 0 3 4,获得锁的顺序却是1 2 3 0 4,这就是非公平锁,它不保证先排队尝试去获取锁的线程一定能先拿到锁
getHoldCount()
getHoldCount()方法返回的是当前线程调用lock()的次数,看一下例子:
public class ThreadDomain43 {private ReentrantLock lock = new ReentrantLock();public void testMethod1() {try {lock.lock();System.out.println("testMethod1 getHoldCount = " + lock.getHoldCount());testMethod2();} finally {lock.unlock();}}public void testMethod2() {try {lock.lock();System.out.println("testMethod2 getHoldCount = " + lock.getHoldCount());} finally {lock.unlock();}}}public static void main(String[] args) {ThreadDomain43 td = new ThreadDomain43();td.testMethod1();}
看一下运行结果:
testMethod1 getHoldCount = 1
testMethod2 getHoldCount = 2
ReentrantLock和synchronized一样,锁都是可重入的,同一线程的同一个ReentrantLock的lock()方法被调用了多少次,getHoldCount()方法就返回多少
getQueueLength()和isFair()
getQueueLength()方法用于获取正等待获取此锁定的线程估计数。注意"估计"两个字,因为此方法遍历内部数据结构的同时,线程的数据可能动态变化
isFair()用来获取此锁是否公平锁
看一下例子:
public class ThreadDomain44 {public ReentrantLock lock = new ReentrantLock();public void testMethod() {try {lock.lock();System.out.println("ThreadName = " + Thread.currentThread().getName() + "进入方法!");System.out.println("是否公平锁?" + lock.isFair());Thread.sleep(Integer.MAX_VALUE);} catch (InterruptedException e) {e.printStackTrace();} finally {lock.unlock();}}}public static void main(String[] args) throws InterruptedException {final ThreadDomain44 td = new ThreadDomain44();Runnable runnable = new Runnable() {public void run() {td.testMethod();}};Thread[] threads = new Thread[10];for (int i = 0; i < 10; i++)threads[i] = new Thread(runnable);for (int i = 0; i < 10; i++)threads[i].start();Thread.sleep(2000);System.out.println("有" + td.lock.getQueueLength() + "个线程正在等待!");}
看一下运行结果:
ThreadName = Thread-0进入方法!
是否公平锁?false
有9个线程正在等待!
ReentrantLock默认的是非公平锁,因此是否公平锁打印的是false。启动了10个线程,只有1个线程lock()了,其余9个等待,都符合预期。
hasQueuedThread()和hasQueuedThreads()
hasQueuedThread(Thread thread)用来查询指定的线程是否正在等待获取指定的对象监视器
hasQueuedThreads()用于查询是否有线程正在等待获取指定的对象监视器
看一下例子,换一个写法,ReentrantLock既然是一个类,就有类的特性,所以这次用继承ReentrantLock的写法,这也是很常见的:
public class ThreadDomain45 extends ReentrantLock {public void waitMethod() {try {lock();Thread.sleep(Integer.MAX_VALUE);} catch (InterruptedException e) {e.printStackTrace();} finally {unlock();}}}public static void main(String[] args) throws InterruptedException {final ThreadDomain45 td = new ThreadDomain45();Runnable runnable = new Runnable() {public void run() {td.waitMethod();}};Thread t0 = new Thread(runnable);t0.start();Thread.sleep(500);Thread t1 = new Thread(runnable);t1.start();Thread.sleep(500);Thread t2 = new Thread(runnable);t2.start();Thread.sleep(500);System.out.println("t0 is waiting?" + td.hasQueuedThread(t0));System.out.println("t1 is waiting?" + td.hasQueuedThread(t1));System.out.println("t2 is waiting?" + td.hasQueuedThread(t2));System.out.println("is any thread waiting?" + td.hasQueuedThreads());}
这里加了几个Thread.sleep(500)保证线程按顺序启动(其实不按顺序启动也关系不大),看一下运行结果:
t0 is waiting?false
t1 is waiting?true
t2 is waiting?true
is any thread waiting?true
由于t0先启动获得了锁,因此不等待,返回false,另外两个线程则要等待获取t0的锁,因此返回的是true,而此ReentrantLock中有线程在等待,所以hasQueuedThreads()返回的是true
isHeldByCurrentThread()和isLocked()
isHeldByCurrentThread()表示此对象监视器是否由当前线程保持
isLocked()表示此对象监视器是否由任意线程保持
看一下例子:
public class ThreadDomain46 extends ReentrantLock {public void testMethod() {try {lock();System.out.println(Thread.currentThread().getName() + "线程持有了锁!");System.out.println(Thread.currentThread().getName() + "线程是否持有锁?" +isHeldByCurrentThread());System.out.println("是否任意线程持有了锁?" + isLocked());Thread.sleep(Integer.MAX_VALUE);} catch (InterruptedException e) {e.printStackTrace();} finally {unlock();}}public void testHoldLock() {System.out.println(Thread.currentThread().getName() + "线程是否持有锁?" +isHeldByCurrentThread());System.out.println("是否任意线程持有了锁?" + isLocked());}}public static void main(String[] args) {final ThreadDomain46 td = new ThreadDomain46();Runnable runnable0 = new Runnable() {public void run() {td.testMethod();}};Runnable runnable1 = new Runnable() {public void run() {td.testHoldLock();}};Thread t0 = new Thread(runnable0);Thread t1 = new Thread(runnable1);t0.start();t1.start();}
看一下运行结果:
Thread-0线程持有了锁!
Thread-1线程是否持有锁?false
Thread-0线程是否持有锁?true
是否任意线程持有了锁?true
是否任意线程持有了锁?true
这个应该很好理解,当前持有锁的是Thread-0线程,所以对于Thread-1来说自然不持有锁。
tryLock()和tryLock(long timeout, TimeUnit unit)
tryLock()方法的作用是,在调用try()方法的时候,如果锁没有被另外一个线程持有,那么就返回true,否则返回false
tryLock(long timeout, TimeUnit unit)是tryLock()另一个重要的重载方法,表示如果在指定等待时间内获得了锁,则返回true,否则返回false
注意一下,tryLock()只探测锁是否,并没有lock()的功能,要获取锁,还得调用lock()方法,看一下tryLock()的例子:
public class ThreadDomain47 extends ReentrantLock {public void waitMethod() {if (tryLock())System.out.println(Thread.currentThread().getName() + "获得了锁");elseSystem.out.println(Thread.currentThread().getName() + "没有获得锁");}}public static void main(String[] args) {final ThreadDomain47 td = new ThreadDomain47();Runnable runnable = new Runnable() {public void run() {td.waitMethod();}};Thread t0 = new Thread(runnable);Thread t1 = new Thread(runnable);t0.start();t1.start();}
看一下运行结果:
Thread-0获得了锁
Thread-1没有获得锁
第一个线程获得了锁返回true,第二个线程自然返回的false。由于有了tryLock()这种机制,如果一个线程长时间在synchronzied代码/synchronized代码块之中,别的线程不得不长时间无限等待的情况将可以被避免。
ReentrantLock中的其他方法
篇幅原因,ReentrantLock中还有很多没有被列举到的方法就不写了,看一下它们的作用:
1、getWaitQueueLength(Condition condition)
类似getQueueLength(),不过此方法的前提是condition。比如5个线程,每个线程都执行了同一个await()的await()方法,那么方法调用的返回值是5,因为5个线程都在等待获得锁
2、hasWaiters(Condition condition)
查询是否有线程正在等待与此锁有关的condition条件。比如5个线程,每个线程都执行了同一个condition的await()方法,那么方法调用的返回值是true,因为它们都在等待condition
3、lockInterruptibly()
如果当前线程未被中断,则获取锁
4、getWaitingThreads(Condition condition)
返回一个collection,它包含可能正在等待与此锁相关给定条件的那些线程,因为构造结果的时候实际线程可能动态变化,因此返回的collection只是尽力的估计值
相关文章:
![](https://www.ngui.cc/images/no-images.jpg)
Java多线程:ReentrantLock中的方法
公平锁与非公平锁 ReentrantLock有一个很大的特点,就是可以指定锁是公平锁还是非公平锁,公平锁表示线程获取锁的顺序是按照线程排队的顺序来分配的,而非公平锁就是一种获取锁的抢占机制,是随机获得锁的,先来的未必就一…...
![](https://img-blog.csdnimg.cn/1ca98012e7874b76bace60c115db1052.png)
RabbitMQ初识快速入门
RabbitMQ初识&快速入门1.初识MQ1.1.同步和异步通讯1.1.1.同步通讯1.1.2.异步通讯1.2.技术对比:2.快速入门2.1.安装RabbitMQ2.1.1 下载镜像2.1.2 安装MQ2.2.RabbitMQ消息模型2.3.导入Demo工程2.4.入门案例2.4.1.publisher实现2.4.2.consumer实现2.5.总结1.初识MQ…...
![](https://img-blog.csdnimg.cn/c7e69890c893422e8f72bbf29263212f.png)
由浅入深了解HashMap源码
由经典面试题引入,讲解一下HashMap的底层数据结构?这个面试题你当然可以只答,HashMap底层的数据结构是由(数组链表红黑树)实现的,但是显然面试官不太满意这个答案,毕竟这里有一个坑需要你去填&a…...
![](https://img-blog.csdnimg.cn/img_convert/6281ee26796febb36ae5c3114915e435.png)
P5318 【深基18.例3】查找文献
题目描述 小K 喜欢翻看洛谷博客获取知识。每篇文章可能会有若干个(也有可能没有)参考文献的链接指向别的博客文章。小K 求知欲旺盛,如果他看了某篇文章,那么他一定会去看这篇文章的参考文献(如果他之前已经看过这篇参考…...
![](https://www.ngui.cc/images/no-images.jpg)
Error caught was: No module named ‘triton‘
虽然报错但是不影响程序运行: A matching Triton is not available, some optimizations will not be enabled. Error caught was: No module named triton解决: pip install -i https://pypi.tuna.tsinghua.edu.cn/simple triton2.0.0.dev20221120...
![](https://www.ngui.cc/images/no-images.jpg)
Ruby设计-开发日志
Log 1 产品 Product 1.1 创建 Product 创建名为 project 的 rails 应用 rails new project创建 Product 模型 rails generate scaffold Product title:string description:text image_url:string price:decimal这会生成一个 migration ,我们需要进一步修改这个…...
![](https://www.ngui.cc/images/no-images.jpg)
SpringBoot 调用外部接口的三种方式
方式一:使用原始httpClient请求 /** description get方式获取入参,插入数据并发起流程* params documentId* return String*/ RequestMapping("/submit/{documentId}") public String submit1(PathVariable String documentId) throws ParseE…...
![](https://img-blog.csdnimg.cn/e19633dfb56d4a74a67ee97d0152c213.png)
C 中的结构体
C 中的结构体 C 数组允许定义可存储相同类型数据项的变量,结构是 C 编程中另一种用户自定义的可用的数据类型,它允许您存储不同类型的数据项。 结构体中的数据成员可以是基本数据类型(如 int、float、char 等),也可以…...
![](https://www.ngui.cc/images/no-images.jpg)
nodejs安装教程
Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时,可以用于在服务器端运行 JavaScript 代码。以下是 Node.js 的安装教程: 步骤 1:下载 Node.js 访问 Node.js 的官方网站 https://nodejs.org/,进入官方下载页面。 在下载页…...
![](https://img-blog.csdnimg.cn/d8efefa125294b5c801780693f19ef23.png)
【华为OD机试】1029 - 整数与IP地址间的转换
文章目录一、题目🔸题目描述🔸输入输出🔸样例1二、代码参考作者:KJ.JK🌈 🌈 🌈 🌈 🌈 🌈 🌈 🌈 🌈 🌈 &#x…...
![](https://img-blog.csdnimg.cn/0345e8de46694dc8a249c6a223fcc8a6.png)
【FPGA实验1】FPGA点灯工程师养成记
对于FPGA几个与LED相关的实验(包括按键点灯、流水灯、呼吸灯等)的记录,方便日后查看。这世界上就又多了一个FPGA点灯工程师了😏 成为一个FPGA点灯工程师分三步:一、按键点灯1、按键点灯程序2、硬件实现二、流水灯1、流…...
![](https://img-blog.csdnimg.cn/c6d713679f8c4c51a2ab81041ed22b7e.png)
操作系统论文导读(三):Stack-based scheduling of realtime processes基于堆栈的实时进程调度
目录 一、论文核心思想: 二、基本的相关条件 作业运行的条件: 作业抢占其他作业的条件: 三、基本的相关定义 四、基本的相关调度 五、基本的相关调度 六、堆栈资源共享 七、与PCP的比较 一、论文核心思想: -引入了一个抢占优…...
![](https://www.ngui.cc/images/no-images.jpg)
音频延时测试方法与实现
音频延时测试方法有以下几种 1、使用专业的测试设备,通过专业的音频测试仪器可以准确测量音频延时,如常见声学分析仪、信号发生器、声卡Smaart(介绍测试延时方法链接:https://blog.csdn.net/weixin_48408892/article/details/1273…...
![](https://www.ngui.cc/images/no-images.jpg)
在 Python 中管理机密的四种方法
我们生活在一个应用程序用于做任何事情的世界,无论是股票交易还是预订沙龙,但在幕后,连接是使用秘密完成的。必须适当管理机密,例如数据库密码、API 密钥、令牌等,以避免任何泄露。 管理机密的需求对任何组织都至关重…...
![](https://www.ngui.cc/images/no-images.jpg)
全国青少年信息素养大赛Python编程挑战赛初赛试题说明
Python 编程挑战赛初赛采用线上考试比赛形式,分为小学组和初中组。不同组别的考核重难点略有不同,考核内容主要是 Python 基础知识,共 30 题,均为单选题,具体考核如下: 小学组考核内容主要是 Python 基础知识,包括输入输出,变量,条件结构,计次循环和无限循环,海龟库…...
![](https://img-blog.csdnimg.cn/0fc52e80716941e39883a0f07379def2.gif)
无需魔法打开即用的 AI 工具集锦
作者:明明如月学长, CSDN 博客专家,蚂蚁集团高级 Java 工程师,《性能优化方法论》作者、《解锁大厂思维:剖析《阿里巴巴Java开发手册》》、《再学经典:《EffectiveJava》独家解析》专栏作者。 热门文章推荐…...
![](https://img-blog.csdnimg.cn/img_convert/38111bed7d48ddec74973dc8a560b9b1.jpeg)
如何进行SEO站内优化,让你的网站更易被搜索引擎收录
我们了解了 SEO 的流程,知道了哪些元素对 SEO 的效果会产生关键影响,接下来,我们就该正式开始动手,打造一个让搜索引擎“爱不释手”的网站。 为了方便理解与记忆,我们将网站划分为几个模块,告诉你优化网站…...
![](https://img-blog.csdnimg.cn/72bd3cc0237a478ca73e8960c5d7ed58.png)
组件内部watch后切换数据报错Error in callback for watcher “xxxx“
报错信息: 报错代码: 百度了一下是因为这里写了箭头函数,导致this指向为父级作用域上下文,不是vue实例导致 修改为: progressData: {handler: function(newValue, oldValue) {this.setChartData(newValue)},deep: …...
![](https://img-blog.csdnimg.cn/img_convert/12cc64701b7d90b0147d887aa1cf05b7.png)
VMware ESXi 7.0 U3l macOS Unlocker OEM BIOS (标准版和厂商定制版)
VMware ESXi 7.0 U3l macOS Unlocker & OEM BIOS (标准版和厂商定制版) 提供标准版和 Dell (戴尔)、HPE (慧与)、Lenovo (联想)、Inspur (浪潮)、Cisco (思科) 定制版镜像 请访问原文链接:https://sysin.org/blog/vmware-esxi-7-u3-oem/,查看最新版…...
![](https://img-blog.csdnimg.cn/1ee0f3cd67e34c419dee6962561abfea.png)
华为阿里版ChatGPT横空出世,谁的成效更好呢?
“你训练的大模型涌现了吗?”“还没有。好难受。”一时间成为了最近AI赛道玩家的一个爆热梗。 不管承不承认,相信每个玩家都不愿意输掉这场激烈的竞争。自百度成为国内“第一个吃螃蟹的人”后,又有两大中国科技巨头做好了准备——华为和阿里…...
![](https://www.ngui.cc/images/no-images.jpg)
【云原生之Docker实战】使用docker部署kooteam在线团队协作工具
【云原生之Docker实战】使用docker部署kooteam在线团队协作工具 一、kooteam介绍1.kooteam介绍2.kooteam的技术选型二、检查本地docker环境1.检查Docker版本2.检查Docker状态三、下载kooteam镜像四、部署kooteam文档管理系统1.创建安装目录2.创建mysql数据库3.新建kooteam数据库…...
![](https://www.ngui.cc/images/no-images.jpg)
ITSS认证是什么认证,itss资质认证
一、ITSS是什么 ITSS根据英文翻译信息技术服务标准(InformationTechnologyServiceStandards,简称ITSS),它既是一套成体系和综合配套的标准库,又是一套选择和提供IT服务的方法学,对企业IT服务而言࿰…...
![](https://img-blog.csdnimg.cn/04fa4675a5224f8e8fe7be574b611135.png)
FTP-----局域网内部远程桌面
此文包含详细的图文教程。有疑问评论区留言。博主第一时间解决。 目录 一、被远程桌面的电脑 1.开启远程权限 2.添加账户,有本地账户跳过这步 3.帐号隶属于 远程桌面 4.帐号隶属于 本地用户组 二、本地电脑连接远程桌面 前提条件: 1.两台电脑在…...
![](https://img-blog.csdnimg.cn/4bd81624e3bc4f95bcb8e805777eddec.png#pic_center)
Learning C++ No.18【STL No.8】
引言: 北京时间:2023/3/18/21:47,周末,不摆烂,但是欠钱终于还是遭报应了,导致坐牢7小时(上午3.5,下午3.5),难受,充分意识到行哥是那么的和蔼可亲…...
![](https://img-blog.csdnimg.cn/ee84c80280ff476cbcd7e6218fca7092.png)
pytorch搭建ResNet50实现鸟类识别
🍨 本文为🔗365天深度学习训练营 中的学习记录博客 🍦 参考文章地址: 365天深度学习训练营-第J1周:ResNet-50算法实战与解析 🍖 作者:K同学啊 理论知识储备 深度残差网络ResNet(dee…...
![](https://img-blog.csdnimg.cn/a41638877cc6437995168433ebba65c8.png#pic_center)
Node.js -- npm与包
1.包 Node.js中的第三方模块又叫做包 就像电脑和计算机指的是相同的东西,第三方模块和包指的是同一概念,只不过叫法不同。 包的来源: 包是由第三方或者个人团队开发出来的,免费供个人使用。 国外有一家IT 公司,叫做n…...
![](https://img-blog.csdnimg.cn/74a9837ebcb444c686de2c274844d888.jpeg#pic_center)
二 、Locust自定义用户(场景)
二 、自定义用户(场景) 一个用户类代表了你系统中的一种用户/场景。当你做一个测试运行时,你指定你想模拟的并发用户的数量,Locust将为每个用户创建一个实例。你可以给这些类/实例添加任何你喜欢的属性,但有一些属性对…...
![](https://img-blog.csdnimg.cn/7d2aaf8d51d14a8e829095c8280a0398.png)
1~3年的测试工程师薪资陷入了瓶颈期,如何突破自己实现涨薪?
对于技术人员而言,职业规划一般分为两个方向:做技术、做管理。进入软件测试行业的新人都会从最基础的执行开始,然后是基本的功能测试。 随后大家会根据个人职业发展来进一步细化,有的走管理路线,成为主管、经理、项目…...
![](https://www.ngui.cc/images/no-images.jpg)
springboot项目前端ajax 07进阶优化,使用jQuery的ajax
使用官网https://jquery.com/ 在下载那里,选择Download the compressed, production jQuery 3.6.4(版本不一样),而后在打开的网页中,选择另存为,就下载好了js文件。 > function doAjax(){ …...
![](https://www.ngui.cc/images/no-images.jpg)
东数西存场景的探索与实践
“东数西算”是通过构建数据中心、云计算、大数据一体化的新型算力网络体系,将东部算力需求有序引导到西部,对优化数据中心建设布局,提升国家整体算力水平,促进绿色发展,扩大有效投资,具有重要意义。 在实…...
![](/images/no-images.jpg)
学做饼干网站/软文广告素材
搭配使用 dao层配置文件(applicationContext-dao.xml): https://blog.csdn.net/a755199443/article/details/90272909 事务管理配置文件(applicationContext-trans.xml): https://blog.csdn.net/a755199443/article/details/90273049 service层配置文件用于扫描service层的Se…...
![](/images/no-images.jpg)
国家城乡和住房建设部网站/今天新闻头条最新消息
电大计算机应用基础考点题库资料小抄一、选择题1、 第一台计算机ENIAC淡生于1946年,是电子管计算机;第二代是晶体管计算机;第三代是中小规模集成电路;第四代是大规模集成电路;2、 计算机的应用领域主要有:科…...
![](https://www.oschina.net/img/hot3.png)
自己网站做短链接/电子商务平台
2019独角兽企业重金招聘Python工程师标准>>> 这个不是很麻烦的事情,毕竟Yii已经做了所有的路由的相关事情,我们只需要配置一下路由规则和nginx就可以了,这里介绍三种nginx配置方案,其实不止Yii,大多数的php框架都可以这样配置 方案一 (这个是网上最多的解决方案,y…...
![](/images/no-images.jpg)
网站手机版跳转代码/微信营销软件
[b]Closure[/b]:如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure)。它只不过是个"内层"的函数,由一个名字&…...
![](/images/no-images.jpg)
龙岗网站制作公司/获客渠道有哪些
插件名说明open in browser浏览器中打开live server实时预览prettier代码格式化 Auto Close Tag Chinese (Simplified) Auto Rename Tag Beautify BEM Helper Code Runner CSS Tree Easy LESS EditorConfig for VS Code Git Graph GitHub Copilot HTML CSS Support Live Server…...
![](https://img-blog.csdnimg.cn/img_convert/a782db77414edcc72bcb595f7052d96a.png)
电子书网站怎么做/接app推广的单子在哪接
前提:使用python3一:Django连接MySQL时默认使用MySQLdb驱动,但MySQLdb不支持Python3,因此这里将MySQL驱动设置为pymysql。具体步骤如下:(1)使用 pip install pymysql 进行安装(2)在项目目录下的__init__.py文件中添加以…...