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

ReentranLock(可重入锁)

一、ReentranLock

ReentranLock属于JUC并发工具包下的类,相当于 synchronized具备如下特点

● 可中断
● 可以设置超时时间
● 可以设置为公平锁(防止线程出现饥饿的情况)
● 支持多个条件变量

与 synchronized一样,都支持可重入

基本语法(synchronized在关键字级别保护临界区, reentrantLock是在对象的级别来保护临界区)

// 获取锁
reentrantLock.lock();
try {// 临界区
} finally {// 释放锁(无论是否出现异常,均会将锁释放)reentrantLock.unlock();
}

lock()与unlock()是成对出现的

1.1 可重入

可重入是指同一个线程对象如果首次获得这把锁,那么因为它是这把锁的拥有者,因此有权利再次获取这把锁
如果是不可重入锁,那么第二次获得锁时,自身也会被锁挡住

import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.locks.ReentrantLock;@Slf4j(topic = "c.Test")
public class Test {// 创建锁重入对象private static ReentrantLock lock = new ReentrantLock();public static void main(String[] args) throws InterruptedException {// 加锁lock.lock();try {log.debug("enter  main");m1();} finally {// 解锁lock.unlock();}}public static void m1() {// 加锁lock.lock();try {log.debug("enter  m1");m2();} finally {// 解锁lock.unlock();}}public static void m2() {// 加锁lock.lock();try {log.debug("enter  m2");} finally {// 解锁lock.unlock();}}
}

运行结果:(锁重入成功)

在这里插入图片描述

1.2 可打断——lockInterruptibly

在等待锁的过程中其他线程可以用interruput()方法终止等待

import cn.itcast.n2.util.Sleeper;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.locks.ReentrantLock;@Slf4j(topic = "c.Test")
public class Test {// 创建锁重入对象private static ReentrantLock lock = new ReentrantLock();public static void main(String[] args)  {Thread t1=new Thread(()->{try {// 尝试获取锁,但可以被打断(如果没有别的线程竞争锁,此方法就会获取lock对象上的锁)/*若有竞争进入阻塞队列等待*/log.debug("尝试获得锁");lock.lockInterruptibly();} catch (InterruptedException e) {e.printStackTrace();log.debug("没有获取锁,返回");return;}try {log.debug("获取到锁");}finally {// 将锁释放掉lock.unlock();}},"t1");// 主线程先对其进行加锁后,t1线程才启动lock.lock();t1.start();// 主线程睡眠1s后打断t1Sleeper.sleep(1);t1.interrupt();}
}

运行结果:(成功打断t1线程)

1.3 锁超时

锁超时:在获取锁的过程中,如果其他线程持有锁一直未释放,去尝试获取锁的线程也不会死等,而是等待一段时间,若这段时间超过对方仍未释放锁,则放弃等待,获取锁失败

可打断属于一种被动的避免无限等待(死等)方式;而锁超时以主动的方式避免死等

1、无其他线程竞争锁:

import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.locks.ReentrantLock;@Slf4j(topic = "c.Test")
public class Test {// 创建锁重入对象private static ReentrantLock lock = new ReentrantLock();public static void main(String[] args) {Thread t1 = new Thread(() -> {log.debug("尝试获得锁");// 尝试获取锁,返回值为布尔型  【成功:获取锁   失败:不可获得锁,不会进入阻塞队列等待】if (!lock.tryLock()) {           //失败则立刻返回(没有任何等待时间)log.debug("获取锁失败");    // falsereturn;}try {// 执行临界区代码log.debug("成功获取锁");} finally {lock.unlock();     // 释放锁}});}
}

运行结果:
在这里插入图片描述

2、存在其他线程竞争(立刻结束):

import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.locks.ReentrantLock;@Slf4j(topic = "c.Test")
public class Test {// 创建锁重入对象private static ReentrantLock lock = new ReentrantLock();public static void main(String[] args) {Thread t1 = new Thread(() -> {log.debug("尝试获得锁");// 尝试获取锁,返回值为布尔型  【成功:获取锁   失败:不可获得锁,不会进入阻塞队列等待】if (!lock.tryLock()) {log.debug("获取锁失败");    // falsereturn;}try {// 执行临界区代码log.debug("成功获取锁");} finally {lock.unlock();     // 释放锁}});// 主线程先对lock对象加锁lock.lock();log.debug("成功获取锁");t1.start();}
}

运行结果:
在这里插入图片描述

3、存在其他线程竞争(等待一段时间):尝试等待1s,1s内若主线程还未释放锁再结束
在这里插入图片描述

哲学家就餐问题便可以使用tryLock()解决

1.4 公平锁

ReentrantLock 默认是不公平的。当一个线程持有锁,其他线程就会进入阻塞队列等待,当锁的持有者释放锁时,阻塞队列中等待的线程会一拥而上,谁先争抢到锁谁便是Owner,而不会按进入阻塞队列的先后顺序先来先得

(通过查看源码发现其构造方法中有一个带boolean类型参数的方法,其参数fair默认为false,可以修改其布尔值保证其公平性)公平锁一般没有必要,会降低并发度

二、ReentranLock条件变量

2.1 简介

条件变量

synchronized 中也有条件变量,就是我们讲原理时那个 waitSet 休息室,当条件不满足时进入 waitSet 等待

ReentrantLock 的条件变量比 synchronized 强大之处在于,它是支持多个条件变量的,这就好比

● synchronized 是那些不满足条件的线程都在一间休息室等消息
● 而 ReentrantLock 支持多间休息室,有专门等烟的休息室、专门等早餐的休息室、唤醒时也是按休息室来唤

使用要点:
● await 前需要获得锁
● await 执行后,会释放锁,进入 conditionObject 等待
● await 的线程被唤醒(或打断、或超时)取重新竞争 lock 锁
● 竞争 lock 锁成功后,从 await 后继续执行

使用例子:

import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import static cn.itcast.n2.util.Sleeper.sleep;@Slf4j(topic = "c.Test24")
public class Test24 {static final Object room = new Object();static boolean hasCigarette = false;static boolean hasTakeout = false;static ReentrantLock ROOM = new ReentrantLock();// 等待烟的休息室(创建一个新的条件变量)static Condition waitCigaretteSet = ROOM.newCondition();// 等外卖的休息室(创建一个新的条件变量)static Condition waitTakeoutSet = ROOM.newCondition();public static void main(String[] args) {new Thread(() -> {// 尝试获取ReentrantLockROOM.lock();try {log.debug("有烟没?[{}]", hasCigarette);while (!hasCigarette) {log.debug("没烟,先歇会!");try {// 进入等烟休息室等待waitCigaretteSet.await();} catch (InterruptedException e) {e.printStackTrace();}}log.debug("可以开始干活了");} finally {// 解锁ROOM.unlock();}}, "小南").start();new Thread(() -> {ROOM.lock();try {log.debug("外卖送到没?[{}]", hasTakeout);while (!hasTakeout) {log.debug("没外卖,先歇会!");try {waitTakeoutSet.await();} catch (InterruptedException e) {e.printStackTrace();}}log.debug("可以开始干活了");} finally {ROOM.unlock();}}, "小女").start();// 送外卖线程sleep(1);new Thread(() -> {ROOM.lock();try {hasTakeout = true;// 唤醒线程waitTakeoutSet.signal();} finally {ROOM.unlock();}}, "送外卖的").start();// 送烟线程sleep(1);new Thread(() -> {ROOM.lock();try {hasCigarette = true;// 唤醒线程waitCigaretteSet.signal();} finally {ROOM.unlock();}}, "送烟的").start();}
}

运行结果:
在这里插入图片描述

相关文章:

ReentranLock(可重入锁)

一、ReentranLock ReentranLock属于JUC并发工具包下的类,相当于 synchronized具备如下特点 ● 可中断 ● 可以设置超时时间 ● 可以设置为公平锁(防止线程出现饥饿的情况) ● 支持多个条件变量 与 synchronized一样,都支持可重…...

Kafka 入门 (一)

Kafka 入门(一) Apache Kafka起源于LinkedIn,后来于2011年成为开源Apache项目,然后于2012年成为First-class Apache项目。Kafka是用Scala和Java编写的。 Apache Kafka是基于发布订阅的容错消息系统。 它是快速,可扩展…...

linux内核开发入门二(内核KO模块介绍、开发流程以及注意事项)

linux内核开发入门二(内核KO模块介绍、开发流程以及注意事项) 一、什么是内核模块 内核模块:ko模块(Kernel Object Module)是Linux内核中的可加载模块,它可以动态地向内核添加功能。在运行时,可…...

设计模式(十七)----行为型模式之模板方法模式

行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。 行为型模式分为类行为模式和对象行为模式,前者采用继承机制来在类间分派行为&…...

【嵌入式Linux内核驱动】01_内核模块

内核模块 宏内核&微内核 微内核就是内核中的一部分功能放到应用层 内核小,精简,可扩展性好,安全性好 相互之间通信损耗多 内核模块 Linux是宏内核操作系统的典型代表,所有内核功能都整体编译到一起,优点是效…...

Spring——数据源对象管理和Spring加载properties文件

前面一直都是在管理自己内部创建的对象&#xff0c;这个是管理外部的对象。 这里先使用阿里巴巴的druid来演示。需要在pom.xml中添加如下的依赖 <dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1…...

Zeek安装、使用与压力测试

Zeek安装与压力测试Zeek安装、简单使用与压力测试环境Zeek安装zeek简单运行安装PF_RING修改Zeek配置文件&#xff0c;使用PF_RING&#xff0c;实现集群流量压力测试查看zeek日志Zeek安装、简单使用与压力测试 科研需要&#xff0c;涉及到Zeek的安装、使用和重放流量压力测试评…...

【javaEE初阶】第三节.多线程 (进阶篇 ) 死锁

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、"死锁"出现的典型场景二、产生 "死锁" 的必要条件 三、解决 "死锁" 问题的办法 总结前言 今天对于多线程进阶的学习&#…...

基于密集连接的轻量级卷积神经网络,用于使用边云架构的露天煤矿服务识别

遥感是快速检测非法采矿行为的重要技术工具。由于露天煤矿的复杂性&#xff0c;目前关于露天煤矿自动开采的研究较少。基于卷积神经网络和Dense Block&#xff0c;我们提出了一种用于从Sentinel-2遥感图像中提取露天煤矿区域的轻量级密集连接网络-AD-Net&#xff0c;并构建了三…...

无刷高速风筒方案介绍--【PCBA方案】

疫情三年过去&#xff0c;春节后&#xff0c;一个新的开始&#xff0c;大家满怀希望畅谈今年好气象。 三年来一波一波的封城、隔离、核酸&#xff0c;经济压抑到了无以复加的地步&#xff0c;也导致了诸多社会问题的出现。消费力被磨平&#xff0c;人们小心翼翼的生活。 常跟…...

花括号展开II[栈模拟dfs]

栈模拟dfs前言一、花括号展开II二、栈模拟dfs总结参考资料前言 递归调用&#xff0c;代码非常的简洁。但是可以通过显式栈来模拟栈中的内容&#xff0c;锻炼自己的代码能力&#xff0c;清楚知道栈帧中需要的内容。 一、花括号展开II 二、栈模拟dfs 每碰到一个左括号&#xf…...

神经网络分类任务(手写数字识别)

1.Mnist分类任务 网络基本构建与训练方法&#xff0c;常用函数解析 torch.nn.functional模块 nn.Module模块 学习方法&#xff1a;边用边查&#xff0c;多打印&#xff0c;duogua 使用jupyter的优点&#xff0c;可以打印出每一个步骤。 2.读取数据集 自动下载 %matplotl…...

FCN网络(Fully Convolutional Networks)

首个端到端的针对像素级预测的全卷积网络 原理&#xff1a;将图片进行多次卷积下采样得到chanel为21的特征层&#xff0c;再经过上采样得到和原图一样大的图片&#xff0c;最后经过softmax得到类别概率值 将全连接层全部变成卷积层&#xff1a;通常的图像分类网络最后几层是全…...

随想录二刷Day15——二叉树

文章目录二叉树2. 递归遍历二叉树3. 二叉树的迭代遍历4. 二叉树的统一迭代法二叉树 2. 递归遍历二叉树 144. 二叉树的前序遍历 class Solution { public:vector<int> preorderTraversal(TreeNode* root) {vector<int> result;preorder(root, result);return res…...

docker-compose部署kafka服务时如何同时允许内外网访问?

背景 最近在学习kafka相关知识&#xff0c;需要搭建自己的kafka环境。综合考虑后决定使用docker-compose来管理维护这个环境。 docker-compose.yml Bitnami的yml文件就很不错&#xff0c;这里直接拿来用了。 version: "2"services:zookeeper:image: docker.io/bi…...

数据结构刷题(二十):17电话号码的字母组合、39组合总和、40组合总和II

一、电话号码的字母组合题目链接思路&#xff1a;回溯三部曲。确定回溯函数参数&#xff1a;题目中给的 digits&#xff0c;还要有一个参数就是int型的index&#xff08;记录遍历第几个数字&#xff0c;就是用来遍历digits的&#xff0c;同时也代表了递归的深度&#xff09;&am…...

Java面试总结(五)

sleep() 方法和 wait() 方法对比 相同点 两者都可以暂停线程的执行&#xff1b;两者都可以响应中断。 不同点 sleep()方法不会释放锁&#xff0c;wait()方法会释放锁&#xff1b; sleep()方法主要用于暂停线程的执行&#xff0c;wait()方法主要用于线程之间的交互/通信&…...

三维人脸实践:基于Face3D的渲染、生成与重构 <二>

face3d: Python tools for processing 3D face git code: https://github.com/yfeng95/face3d paper list: PaperWithCode 3DMM方法&#xff0c;基于平均人脸模型&#xff0c;可广泛用于基于关键点的人脸生成、位姿检测以及渲染等&#xff0c;能够快速实现人脸建模与渲染。推…...

在linux上部署Java项目

在Linux部署Java环境 要是想要部署java web程序,首先要配置环境 jdk tomcat mysql 安装jdk 推荐的方法是使用yum直接安装openjdk(开源的,与官方的jdk功能差不多),目前使用的最多的就是jdk8系列 yum list | grep jdk 在源上搜索所有关于jdk的文件 devel表示development的意思…...

线性表的接口

线性表的实现方式 顺序表 顺序表是一种线性表的实现方式&#xff0c;它是用一组地址连续的存储单元依次存储线性表中的数据元素&#xff0c;使得逻辑上相邻的元素在物理上也相邻⁴。顺序表可以用数组来实现&#xff0c;它的优点是可以快速定位第几个元素&#xff0c;但是缺点…...

XCTF-web-easyupload

试了试php&#xff0c;php7&#xff0c;pht&#xff0c;phtml等&#xff0c;都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接&#xff0c;得到flag...

基于大模型的 UI 自动化系统

基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

Java 语言特性(面试系列1)

一、面向对象编程 1. 封装&#xff08;Encapsulation&#xff09; 定义&#xff1a;将数据&#xff08;属性&#xff09;和操作数据的方法绑定在一起&#xff0c;通过访问控制符&#xff08;private、protected、public&#xff09;隐藏内部实现细节。示例&#xff1a; public …...

React Native 导航系统实战(React Navigation)

导航系统实战&#xff08;React Navigation&#xff09; React Navigation 是 React Native 应用中最常用的导航库之一&#xff0c;它提供了多种导航模式&#xff0c;如堆栈导航&#xff08;Stack Navigator&#xff09;、标签导航&#xff08;Tab Navigator&#xff09;和抽屉…...

ElasticSearch搜索引擎之倒排索引及其底层算法

文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

Element Plus 表单(el-form)中关于正整数输入的校验规则

目录 1 单个正整数输入1.1 模板1.2 校验规则 2 两个正整数输入&#xff08;联动&#xff09;2.1 模板2.2 校验规则2.3 CSS 1 单个正整数输入 1.1 模板 <el-formref"formRef":model"formData":rules"formRules"label-width"150px"…...

NPOI Excel用OLE对象的形式插入文件附件以及插入图片

static void Main(string[] args) {XlsWithObjData();Console.WriteLine("输出完成"); }static void XlsWithObjData() {// 创建工作簿和单元格,只有HSSFWorkbook,XSSFWorkbook不可以HSSFWorkbook workbook new HSSFWorkbook();HSSFSheet sheet (HSSFSheet)workboo…...

C# 表达式和运算符(求值顺序)

求值顺序 表达式可以由许多嵌套的子表达式构成。子表达式的求值顺序可以使表达式的最终值发生 变化。 例如&#xff0c;已知表达式3*52&#xff0c;依照子表达式的求值顺序&#xff0c;有两种可能的结果&#xff0c;如图9-3所示。 如果乘法先执行&#xff0c;结果是17。如果5…...

uniapp 实现腾讯云IM群文件上传下载功能

UniApp 集成腾讯云IM实现群文件上传下载功能全攻略 一、功能背景与技术选型 在团队协作场景中&#xff0c;群文件共享是核心需求之一。本文将介绍如何基于腾讯云IMCOS&#xff0c;在uniapp中实现&#xff1a; 群内文件上传/下载文件元数据管理下载进度追踪跨平台文件预览 二…...

Vue 模板语句的数据来源

&#x1f9e9; Vue 模板语句的数据来源&#xff1a;全方位解析 Vue 模板&#xff08;<template> 部分&#xff09;中的表达式、指令绑定&#xff08;如 v-bind, v-on&#xff09;和插值&#xff08;{{ }}&#xff09;都在一个特定的作用域内求值。这个作用域由当前 组件…...