可重入锁是什么?

2023-11-18

本文内容如有错误、不足之处,欢迎技术爱好者们一同探讨,在本文下面讨论区留言,感谢。

简介

可重入锁在Java中有synchronizeReentrantLock,其中synchronize是在JVM中进行可重入控制,ReentrantLock是在代码中实现可重入控制。

在Java 5.0中,增加了一个称为ReentrantLock的新功能,以增强内部锁定功能。在此之前,“synchronized" 和 "volatile”是实现并发的手段。

public synchronized void doAtomicTransfer(){
     //进入同步代码块 获取对此对象的锁定。
    operation1()
    operation2();    
} // 退出同步代码块, 释放(release)对此对象的锁定。

同步使用内部锁或监视器。Java中的每个对象都有一个与之关联的固有锁。每当线程尝试访问同步的块或方法时,它都会获取该对象的固有锁定或监视器。在使用静态方法的情况下,线程获取对类对象的锁定。就编写代码而言,内在锁定机制是一种干净的方法,对于大多数用例而言,它是相当不错的。

那么,为什么我们需要显式锁的附加功能?

内部锁定机制可能具有一些功能限制,例如:

  1. 无法中断等待获取锁的线程(lock Interruptibly)。
  2. 如果不愿意永远等待,就无法尝试获取锁(try lock)。
  3. 无法实现非块结构的锁定规则,因为必须在获取它们的同一块中释放固有锁。
ReentrantLock
void lock();
void lockInterruptibly() throws InterruptedException;
boolean tryLock();
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
.....

ReentrantLock

中断锁获取

可中断的锁获取允许在可取消的活动中使用锁。

该的lockInterruptibly方法可以让我们尝试,同时可中断获取锁。因此,基本上,它允许线程立即响应从另一个线程发送给它的中断信号。

例子:假设有一条共享线路来发送消息。希望以这样一种方式设计它:如果另一个线程来了并中断当前线程,则锁应释放并执行退出或关闭操作以取消当前任务。

public boolean sendOnSharedLine(String message) throws InterruptedException{
	lock.lockInterruptibly();
	try{
		return cancellableSendOnSharedLine(message);
	} finally {
		lock.unlock();
	}
}

private boolean cancellableSendOnSharedLine(String message){
.......
可重入设计的意义

广义上的可重入锁指的是可重复可递归调用的锁,在外层使用锁之后,在内层仍然可以使用,并且不发生死锁(前提得是同一个对象或者class),这样的锁就叫做可重入锁。

这样可以避免每次获取锁之后,在操作资源后,释放锁再获取锁,每次释放锁再获取锁的调度切换是很耗资源。

避免子类改写了父类的 synchronized 方法,调用子类时发生死锁。

不可重入锁
class UnReentantLock{
    private AtomicReference<Thread> owner = new AtomicReference<>();

    /**
     * 获取锁
     */
    public void lock(){
        Thread current = Thread.currentThread();
        // 自旋锁实现,同样可以使用do while
        //for (; ; ) {
        //    if (!owner.compareAndSet(null, current)) {
        //        return ;
        //    }
        //}
        do {

        } while (!owner.compareAndSet(null, current));
        return;
    }

    /**
     * 释放锁
     */
    public void unLock(){
        Thread current = Thread.currentThread();
        owner.compareAndSet(current, null);
    }
}

这里使用了原子引用和CAS

CAS的原理是Unsafe类和自旋锁,上面已经展示自旋锁如何使用,下面图片是Unsafe类中的一个native方法的c++实现,可以查看 JVM 本地方法栈(native method stack)解释
Unsafe方法内部实现

不可重入改为可重入

可重入锁实现是通过计数器来实现可重入多次。


ReentrantLock lock = new ReentrantLock();
lock.lock();
lock.lock();

try{
...
}finally{
	lock.unlock();
	lock.unlock();
}

上面的代码可以说明,加了几次lock()就要执行几次unlock();

下面是改造代码:
借鉴:https://blog.csdn.net/wuseyukui/article/details/72312574

class NumberReentrantLock{
    private AtomicReference<Thread> owner = new AtomicReference<>();
    private int lockNumber = 0;

    public void lock(){
        Thread current = Thread.currentThread();
        // 使用== 表示是同一个引用
        if (current == owner.get()) {
            lockNumber++;
            return;
        }
        do {

        } while (!owner.compareAndSet(null, current));
    }

    public void unlock(){
        Thread current = Thread.currentThread();
        if (current == owner.get()) {
            if (lockNumber == 0) {
                owner.compareAndSet(current, null);
            }else{
                lockNumber--;
            }
        }
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

可重入锁是什么? 的相关文章

  • java 回调函数解读

    模块间调用 在一个应用系统中 无论使用何种语言开发 必然存在模块之间的调用 调用的方式分为几种 1 同步调用 同步调用是最基本并且最简单的一种调用方式 类A的方法a 调用类B的方法b 一直等待b 方法执行完毕 a 方法继续往下走 这种调用方
  • Java 序列化详解

    Java 序列化 Serialization 是指将一个 Java 对象转换成字节序列 以便在网络上传输或存储在本地磁盘中 而反序列化 Deserialization 则是将已经序列化的字节序列恢复为 Java 对象 Java 提供了自带的
  • IDEA 【基础】 javaweb项目中 将maven的jar包,复制到web项目的 lib 文件夹

    自己在做小型javweb项目的时候经常遇到这种问题 java lang NoClassDefFoundError 明明maven已经添加依赖了 而且项目里面可以正常运行 但是启动tomcat运行的时候 却运行不了 博主琢磨半天 了解到 第三
  • 并发锁分析

    锁 为什么加锁 并发会造成数据混乱 事务 原子性a 一致性c 隔离性i 持久性d 加锁的影响和优化点 线程切换的开销 缓存命中率 加锁失败会进行线程切换 用户态和内核态的切换开销 栈的切换 寄存器切换 synchronized重量锁的实现是
  • websocket 发送内容长度设置(默认8192字节)

    https blog csdn net zhaotian19871204 article details 84801915
  • Java 如何对中文排序

    字符串的 compareTo 方法是不能对中文排序的 下面这个例子中的中文使用 compareTo 方法排序后得到的是乱序 List
  • Java 网络安全

    1 常见的 Web 攻击 1 1 CSRF攻击 1 1 1 CSRF如何防护 1 2 XSS 攻击 1 2 1 XSS 攻击分类 1 2 2 XSS 防护 1 3 DOS 攻击 1 3 1 防护 1 4 SQL 注入 1 4 1 SQL 注
  • Java 8 lambda 函数式编程

    目录 简介 Lambda 表达式 解析1 解析2 自定义 lambda 表达式 例子1 一行输出多个值 例子2 数值计算 例子3 函数中使用自定义lambda表达式 简介 函数式编程就是类似于这样的东西 class MyTest publi
  • 比较两个list是否相等

    比较两个list是否相等 public booelan equalsList List
  • Artifactory Maven 使用教程

    Maven 仓库使用 修改 Maven 配置文件 选择左侧 Artifacts 选择自己需要上传的 Maven 仓库 点击Set Me Up 在弹出的设置框中点击 点击下载生成的文件 将生成的文件放到此目录下 或者你自己的 Maven 目录
  • 良好的Java编程风格

    良好的Java编程风格 正确的注释和注释风格 使用文档注释来注释整个类或整个方法 如果注释方法中的某一个步骤 使用单行或多行注释 正确的缩进和空白 使用一次 tab 操作 实现缩进 运算符两边习惯性各加一个空格 比如 2 4 5 块的风格
  • java是值传递还是引用传递

    文章目录 1 前言 2 java是值传递还是引用传递 1 前言 java是值传递 值传递是指在调用方法时将实际参数拷贝一份传递到方法中 这样在方法中如果对参数进行修改 将不会影响到实际参数 当传的是基本类型时 传的是值的拷贝 对拷贝变量的修
  • ‘mvn’ 不是内部或外部命令,也不是可运行的程序 或批处理文件

    话不多说 先来一张图 提示 mvn 不是内部或外部命令 也不是可运行的程序 或批处理文件 这说明 Windows系统找不到mvn相关的命令 基本上就是环境变量没有配置 或者配置出错 操作步骤 搜索环境变量 打开 点击环境变量 在用户变量中
  • java 驼峰和下划线互相转换

    其实是很简单的正则表达式转换 直接上代码 驼峰转下划线 param str 目标字符串 return java lang String public static String humpToUnderline String str Stri
  • java 静态代理和动态代理

    什么是代理 从字面意思来说 代理就是代替处理的意思 从程序层面来说 代理就是代替某个程序 处理某个事情 静态代理 场景1 小明需要买基金 public class Main public static void main String ar
  • JAVA 【基础】 log4j 输出样式

    先了解一下log4j 的打印参数如下 参数 说明 L 输出代码中的行号 l 输出日志事件的发生位置 包括类目名 发生的线程 以及在代码中的行数 如 Testlog main TestLog java 10 m 输出代码中指定的消息 p 输出
  • JAVA 通过浏览器下载大文件导致OOM

    背景 Response 获取的对象为 ContentCachingResponseWrapper 页面点击下载文件 后台报错如下 org springframework web util NestedServletException Han
  • java 反射泛型工具类, 获取类的泛型类型

    直接上代码 public class ParameterizedTypeUtils 根据索引获取泛型实例类 param type 类型 param index return java lang Class
  • JAVA【基础】 IDEA导入jar包的几种方式

    目录 获取想要添加的依赖 或者jar包 maven添加依赖 手动导入jar包 最后测试一下 是否添加成功 下面多图预警 获取想要添加的依赖 或者jar包 添加依赖 或者下载jar包 都可以去maven网站下载 进入 Maven仓库 http
  • Java 比较器 -- 对象比较

    基本数据类型比较大小时 我们可以用比较运算符 当两个对象比较大小时 我们就可以用比较器了 实现的方式有两种 如下 方式一 自然排序 实现接口Comparable 创建一个自定义类Students 实现接口Comparable 并重写comp

随机推荐

  • QT槽函数的使用

    QT槽函数的使用 例如 在头文件中设置槽函数 public slots void OnClickedButtonEnsure void OnClickedButtonExit cpp文件 构造函数中写入 connect ui pushBut
  • STM32F103ZET6【标准库函数开发】------配置定时器参数的几个常用函数

    TIM TimeBaseInitTypeDef 基本初始化 TIM OCInitTypeDef 比较输出初始化 TIM ICInitTypeDef 输入捕获初始化 TIM BDTRInitTypeDef 断路和死区初始化 TIM TimeB
  • pycharm创建的虚拟环境为什么用conda env list命令查询不到?

    问题描述 pycharm创建的虚拟环境为什么用conda env list命令查询不到 pycharm开发环境可以创建虚拟环境 目的是为隔绝其他环境种库带来的版本干扰 但是发现一个问题 无论是在windows终端 anaconda终端 Py
  • Java课程设计-学籍信息管理系统

    一 系统分析 学生的学籍信息是记录学生的重要信息档案 如何以电子文档形式记录下学生的学籍信息是每个学校必须做的事情 该学生学籍信息管理系统就是为了方便学校记录下每一个学生的基本信息 生成电子数据库 并且能够做到查询 更改 删除 浏览等功能操
  • Unity 移动端触摸屏操作

    Unity 触屏操作 当将Unity游戏运行到IOS或Android设备上时 桌面系统的鼠标左键可以自动变为手机屏幕上的触屏操作 但如多点触屏等操作却是无法利用鼠标操作进行的 Unity的Input类中不仅包含桌面系统的各种输入功能 也包含
  • 关于类和对象

    1 面向对象是一种技术的开发模式 但是最早的时候所使用的模式是面向过程 面向对象就是一种组件化的设计思想 面向过程 指的是针对于某一问题单独提出解决方案及代码开发 面向对象 以一种组件化的形势进行代码的设计 这样开发出来的代码有一个最大的好
  • Python Tkinter实现简单文本编辑器

    下面看看如何利用Tkinter实现一个文本编辑器 语言 python 运行效果 在 Python 代码中使用 Tkinter 的简单文本编辑器应用程序 这 使用Tkinter的简单文本编辑器应用程序 是编码在 python 程序设计语言 该
  • [编写高质量代码:改善java程序的151个建议]建议103 反射访问属性或方法时将Accessible设置为true...

    转载于 https www cnblogs com akingseu p 3506576 html
  • canvas小练习之鼠标粒子特效

  • Qt 笔记5--Qt 拉伸窗体

    Qt 笔记5 Qt 拉伸窗体 正常情况下 Qt主窗体拉伸 但内部子窗体大小及位置并未发生该表 导致出现一部分空白区域 因此实际中为了美观需要实现其动态拉伸和调整效果 以下为笔者通过重新resizeEvent方法实现的一个简单拉伸案例 相应学
  • 小程序如何进行分包详细介绍

    微信小程序开发过程中 随着业务不断迭代 程序包的体积越来越大 使用分包加载是开发者必须面对的问题 正常情况下 小程序首次启动时 会将整个代码包下载下来 所以如果代码包过大 会影响小程序首次启动时间 因此微信官方对小程序代码包做了大小限制 官
  • JetBrains Resharper 2019.1.3的安装、破解、使用

    最近在浏览GitHub时 看到好多项目下面会有如下图标 几经折腾之后 发现这个一个非常好用的VS插件 称为神级也不为过 可以进行编写提示 代码重构 文件搜索等许多操作 当然目前最新版的VS中已经具有很多类似的功能 但是这个插件从实用性上来说
  • 2014年2月7日星期五(7-3,消除了背面的3D线框立方体)

    好久没进行了 看看吧 与DEMO7 2的区别 只看不同的地方 相机类型不同 归一化平面改为2 2 ar 视口为640 480 执行了背面消除 就是判断面元向量与面元到视点向量的点乘 gt 0 则可见 否则 消除 这一步是在物体剔除后和世界坐
  • 百度飞浆零基础实践深度学习入门课,通过PaddlePaddle实现波士顿房价预测

    百度架构师手把手带你零基础实践深度学习 课程已加入学习 对深度学习有了深入浅出对理解 并通过两种方式实现波士顿房价预测的算法 包括Python和Numpy构建深度学习框架 以及使用paddlepaddle快速搭建 快速实现预测 A 使用Py
  • 使用pl.droidsonroids.gif.GifImageView在安卓中显示动图遇到的问题

    在做一款聊天软件 其中聊天界面需要发送表情 而表情都是动图 在安卓中想要显示动图 就要借助第三方框架 我选的是pl droidsonroids gif GifImageView 使用方法如下 你在github上下载了android gif
  • Webpack5 处理图片资源、图标资源、修改输出目录、清空上一次打包的所有文件

    1 处理图片资源 Webpack5 已经将两个 Loader file loader 和 url loader 功能内置到 Webpack 里了 我们只需要简单配置即可处理图片资源 优化 gt 小图片转化为base64 小图片可以转换为ba
  • android分析monkey的anr

    1 根据anr信息和traces txt判断anr是发生在那个进程中 2 在文件夹logs4android x中搜索 ANR 或者在monkeylog中搜索 anr in 找到发生anr的时间 3 在文件夹logs4android x中搜索
  • 基于深度路由的水下传感器网络(翻译、整理)

    基于深度路由的水下传感器网络 翻译 整理 背景与意义 无线传感器网络引起了研究人员的广泛关注 并在该领域取得了很大进展 起初 这些网络仅涵盖地面的实用程序 但后来 由于在地球被 70 水覆盖 所以大家开始研究传感器网络的水下应用 也就是我们
  • 超声非线性成像-谐波成像基本知识

    文章目录 概述 超声的非线性 组织谐波成像 组织谐波的提取方法 组织谐波成像的优点 造影谐波成像 应用实例 总结 参考文献 概述 最近了解了一下非线性超声中的谐波成像 可以作为知识普及了解一下 大部分来自于文献 如有遗漏可以私信咸鱼进行修改
  • 可重入锁是什么?

    本文内容如有错误 不足之处 欢迎技术爱好者们一同探讨 在本文下面讨论区留言 感谢 文章目录 简介 ReentrantLock 中断锁获取 可重入设计的意义 不可重入锁 不可重入改为可重入 简介 可重入锁在Java中有synchronize和