Java那些“锁”事 - 可重入锁(递归锁)

        可重入锁是一种线程同步的机制,它允许线程多次获取同一个锁,而不会产生死锁。可重入锁的特点是在持有锁的情况下可以再次进入同步代码块或方法,而不会被阻塞。ReentrantLock和synchronized都是可重入锁。ReentrantLock属于显式可重入锁,synchronized属于隐式可重入锁。

synchronized案例

    public static void main(String[] args) {final Object object = new Object();new Thread(() -> {synchronized (object) {System.out.println(Thread.currentThread().getName() + " 外层调用");synchronized (object) {System.out.println(Thread.currentThread().getName() + " 中层调用");synchronized (object) {System.out.println(Thread.currentThread().getName() + " 内层调用");}}}}, "A").start();}

        打印信息:

A 外层调用
A 中层调用
A 内层调用

        如上面代码中,线程A外层调用已经获得object锁对象,中层调用时需要同样需要获得object锁对象,但是最外层并没有释放object锁对象,但是线程A照样能进入到代码的中层。内层也是一样的逻辑。简单来说:在一个synchronized修饰的方法或者代码块的内部调用本类的其他synchronized修饰的方法或者代码块时,是可以永远获得锁的。

        每个对象多可以成为一个锁对象,都拥有一个锁计数器和指向持有该锁的线程的指针。当monitorenter时,如果目标锁对象的计数器为零,那么说明它没有被其他线程所持有,java虚拟机将该锁对象的持有线程设置为当前线程,并且将其计数器+1。在目标锁对象的计数器不为零的情况下,如果锁对象的持有线程时当前线程,那么虚拟机可以将其计数器+1,否则需要等待,直到持有线程释放该锁。当执行monitoreexit时,java虚拟机则需要将锁对象的计数器-1,计数器为零代表该锁已经被释放。

ReentrantLock案例

 public static void main(String[] args) {final Lock lock = new ReentrantLock();new Thread(() -> {lock.lock();try {System.out.println(Thread.currentThread().getName() + " 进入最外层");lock.lock();try {System.out.println(Thread.currentThread().getName() + " 进入中间层");} finally {//正常情况下,加锁几次就需要解锁几次。如果没有unlock,B线程就获取不到锁。lock.unlock();}} finally {//正常情况下,加锁几次就需要解锁几次。如果没有unlock,B线程就获取不到锁。lock.unlock();}}, "A").start();new Thread(() -> {lock.lock();try {System.out.println(Thread.currentThread().getName() + " 进入最外层");} finally {lock.unlock();}}, "B").start();}

        打印结果:

A 进入最外层
A 进入中间层
B 进入最外层

        案例中,A线程需进入最外层已经获得lock对象,想要进入中间层也需要获得lock对象,但是进入中间层之前并没有unlock。

        还有一点需要注意的是,A线程获得lock对象几次就与之相对应的unlock几次,不然线程B根本无法获得lock对象。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue源码学习 - 异步更新队列 和 nextTick原理

目录 前言一、Vue异步更新队列二、nextTick 用法三、原理分析四、nextTick 源码解析1)环境判断2)nextTick() 五、补充 前言 在我们使用Vue的过程中,基本大部分的 watcher 更新都需要经过 异步更新 的处理。而 nextTick 则是异步更新的核心。…

MacOS本地安装Hadoop3

金翅大鹏盖世英,展翅金鹏盖世雄。 穿云燕子锡今鸽,踏雪无痕花云平。 ---------------- 本文密钥:338 ----------------- 本文描述了在macbook pro的macos上安装hadoop3的过程,也可以作为在任何类linux平台上安装hadoop3借鉴。 …

4、Linux驱动开发:设备-设备号设备号注册

目录 🍅点击这里查看所有博文 随着自己工作的进行,接触到的技术栈也越来越多。给我一个很直观的感受就是,某一项技术/经验在刚开始接触的时候都记得很清楚。往往过了几个月都会忘记的差不多了,只有经常会用到的东西才有可能真正记…

Verilog语法学习——LV2_异步复位的串联T触发器

LV2_异步复位的串联T触发器 题目来源于牛客网 [牛客网在线编程_Verilog篇_Verilog快速入门 (nowcoder.com)](https://www.nowcoder.com/exam/oj?page1&tabVerilog篇&topicId301) 题目 题目描述: 用verilog实现两个串联的异步复位的T触发器的逻辑&#x…

MATLAB算法实战应用案例精讲-【深度学习】预训练模型GPTXLNet

目录 GPT 1. 介绍 1.1 GPT的动机 2. 模型结构 3. GPT训练过程 3.1 无监督的预训练

【LeetCode】141.环形链表

题目 给你一个链表的头节点 head ,判断链表中是否有环。 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置&#…

opencv-22 图像几何变换01-缩放-cv2.resize()(图像增强,图像变形,图像拼接)

什么是几何变换? 几何变换是计算机图形学中的一种图像处理技术,用于对图像进行空间上的变换,而不改变图像的内容。这些变换可以通过对图像中的像素位置进行调整来实现。 常见的几何变换包括: 平移(Translation&#x…

IT行业面试攻略:技巧与心态的平衡

引言:在面试IT公司时,调整好心态是取得优秀表现的关键。面试心态直接影响着我们在面试中的自信程度和表现。面对这一挑战,我们需要学会积极自信、认识到紧张是正常的、进行充分准备以及以积极的心态去迎接面试。只有在拥有正确的心态下&#…

STM32MP157驱动开发——按键驱动(tasklet)

文章目录 “tasklet”机制:内核函数定义 tasklet使能/ 禁止 tasklet调度 tasklet删除 tasklet tasklet软中断方式的按键驱动程序(stm32mp157)tasklet使用方法:button_test.cgpio_key_drv.cMakefile修改设备树文件编译测试 “tasklet”机制: …

【Ansible】Ansible自动化运维工具之playbook剧本

playbook 一、playbook 的概述1. playbook 的概念2. playbook 的构成 二、playbook 的应用1. 安装 httpd 并启动2. 定义、引用变量3. 指定远程主机 sudo 切换用户4. when条件判断5. 迭代6. Templates 模块6.1 添加模板文件6.2 修改主机清单文件6.3 编写 playbook 7. tags 模块 …

vue权限按钮的实现

鉴权函数 由于下面几种方式都需要用到鉴权函数,所以将其放置在组件外面,供组件或其他文件调用。 // src/utils/hasPermission.jsimport { usePermissionStore } from /stores import array from lodash/array export const hasPermission (value, def…

Java 设计模式 - 单例模式 - 保证类只有一个实例

单例模式 - 保证类只有一个实例 为什么使用单例模式?单例模式的实现方式1. 饿汉式(Eager Initialization)2. 懒汉式(Lazy Initialization)3. 双重检查锁(Double-Checked Locking)4. 静态内部类&…

EXCEL,如何比较2个表里的数据差异(使用数据透视表)

目录 1 问题: 需要比较如下2个表的内容差异 1.1 原始数据喝问题 1.2 提前总结 2 使用EXCEL公式方法 2.1 新增辅助列: 辅助index 2.2 具体公式 配合条件格式 使用 3 数据透视表方法 3.1 新增辅助列: 辅助index 3.2 需要先打开 数据透视表向导 …

微信小程序开发6

一、分包-基础概念 1.1、什么是分包 分包指的是把一个完整的小程序项目,按照需求划分为不同的子包,在构建时打包成不同的分包,用户在使用时按需进行加载。 1.2、分包的好处 对小程序进行分包的好处主要有以下两点: 可以优化小程序…

Ubuntu 20.04 Ubuntu18.04安装录屏软件Kazam

1.在Ubuntu Software里面输入Kazam,就可以找不到这个软件,直接点击install就可以了 2.使用方法: 选择Screencast(录屏) Fullscreen(全屏)-----Windows(窗口)--------Ar…

20.3 HTML表格

1. table表格 table标签是HTML中用来创建表格的元素. table标签通常包含以下子标签: - th标签: 表示表格的表头单元格(table header), 用于描述列的标题. - tr标签: 表示表格的行(table row). - td标签: 表示表格的单元格(table data), 通常位于tr标签内, 用于放置单元格中的…

数据结构之动态顺序表(附带完整程序)

🎈基本概念 🌈一.线性表、顺序表的定义 ☀️(1)线性表: 是n个具有相同特性的数据元素的有限序列。线性表在逻辑上是线性结构,但在物理上存储时,通常以数组和链式结构的形式存储。 ☀️&…

c# 此程序集中已使用了资源标识符

严重性 代码 说明 项目 文件 行 禁止显示状态 错误 CS1508 此程序集中已使用了资源标识符“BMap.NET.WindowsForm.BMapControl.resources” BMap.NET.WindowsForm D:\MySource\Decompile\BMap.NET.WindowsForm\CSC 1 活动 运行程序时&a…

【NetCore】04-作用域与对象释放行为

文章目录 作用域 作用域由IServiceScope接口承载 对象释放 实现IDisposable接口类型释放 1.DI只负责释放由其创建的对象实例 2.DI在容器或子容器释放时,释放由其创建的对象实例 建议 1.避免在根容器获取实现IDisposable接口的瞬时服务 2.避免手动创建实现了IDispo…

uniAPP 浙政钉 入门手册

uniAPP 如何运行钉钉小程序: 运行钉钉小程序 调试工具导入项目 及 相关平台使用: 专有钉钉 浙政钉 前端 对接流程 常见调试工具,遇到的问题: 采坑记录 下载小程序 IDE 环境配置文件 专有钉钉–环境配置文件