Java中的ReentrantLock实现原理

ReentrantLock的实现原理 ReentrantLock 简介 ReentrantLock 实现了 Lock 接口,是一种可重入的独占锁。 相比于 synchronized 同步锁,ReentrantLock 更加灵活,拥有更加强大的功能,比如可以实现公平锁机制。 首先,先来了解一下什么是公平锁机制。 ReentrantLock 的公平锁机制 我们知道,ReentrantLock 分为公平锁和非公平锁,可以通过构造方法来指定具体类型: //默认非公平锁 public ReentrantLock() { sync = 阅读详情

Java中的ReentrantLock实现原理

在并发编程中,线程安全问题一直是非常重要的问题。Java中提供了多种解决线程安全问题的机制,其中一个比较常用的就是ReentrantLock。本文将介绍ReentrantLock的实现原理,从原子性、可见性等方面解释并结合源码分析,以便更好地理解在多线程环境下实现线程安全的过程。

ReentrantLock概述

ReentrantLock是Java并发包下的一个类,它提供了与synchronized关键字类似的功能,可以实现对共享资源的访问控制,从而保证线程安全。相比于synchronized关键字,ReentrantLock需要更为复杂的使用方式,但是其灵活性更强,同时可以支持更高级别的需求。

ReentrantLock的构造函数可以接受一个参数fair,表示是否采用公平锁方式,默认为false,即非公平锁。

为什么需要ReentrantLock

synchronized关键字是Java中最基本的线程同步机制,其优点是简单易用,但是其缺点也是显而易见的。由于synchronized关键字是Java语言级别的,因此其性能较差,且不容易进行灵活的定制。当需要使用比较复杂的同步机制时,synchronized关键字就显得力不足。

而ReentrantLock通过提供可定制的同步机制,弥补了synchronized关键字的缺点。ReentrantLock的使用方式更为灵活,支持多种同步策略,可以很好地满足不同的需求。同时,由于ReentrantLock是基于Java并发包中的API实现的,因此它的运行效率较高。

ReentrantLock实现原理

ReentrantLock的实现原理可以分为两个方面,即锁的获取和锁的释放。

锁的获取

在ReentrantLock中,锁的获取是通过调用lock()方法来实现的。其核心思想是:当一个线程请求一个未被锁定的ReentrantLock时,该线程将获得锁并进入临界区,阻止其他线程进入临界区;当另一个线程请求相同的锁时,如果该锁已经被另一个线程占用,则该线程会被阻塞,并一直等待直到该锁被释放后才能重新尝试获取该锁。

但是,ReentrantLock的获取锁过程并不是简单地采用同步机制来实现的,而是涉及到一些底层的机制。具体来说,ReentrantLock采用了以下三种机制来实现锁的获取:

1. 原子性

在ReentrantLock的实现中,对于每个线程来说都会有一个state变量,其代表当前线程获取到的锁重入次数。当一个线程首次获取锁时,state的值为0。如果该线程再次获取锁,state的值就会增加1。相应地,当该线程释放锁时,state值将减少1。

这样一来,在ReentrantLock中,锁的获取过程就涉及到了原子性的问题。因此,ReentrantLock使用了CAS(Compare and Swap)机制来确保锁的获取操作是原子性的。简单来说,CAS机制就是在多线程环境下,当多个线程同时尝试修改同一个变量时,只有一个线程能够成功修改,其他线程将被阻塞。

2. 可重入性

在ReentrantLock中,还需要支持可重入性,即一个线程可以多次获取同一个锁。为了实现这个功能,ReentrantLock会为每个线程记录已经获取到的锁的状态信息,并确保在释放所有已获取的锁之前不允许其他线程获取这些锁。因此,ReentrantLock的可重入性是通过这种方式实现的。

3. 队列机制

除了原子性和可重入性外,ReentrantLock还采用了队列机制来确保锁的获取顺序。具体来说,当多个线程请求同一把锁时,它们会被加入到一个FIFO队列中。锁的所有者会在释放锁时,唤醒队列中的下一个线程,从而实现锁的获取顺序。

锁的释放

与锁的获取不同,锁的释放过程相对简单。在ReentrantLock中,锁的释放是通过调用unlock()方法来实现的。具体来说,当一个线程调用unlock()方法释放锁时,ReentrantLock会将该线程的state值减少1,如果state值变为0,则锁被完全释放,并允许其他线程尝试获取该锁。

ReentrantLock源码分析

通过上述的介绍,我们可以初步了解ReentrantLock的实现原理。现在,我们再来结合源码分析,更深入地理解ReentrantLock的工作原理。

构造函数

首先,我们来看一下ReentrantLock的构造方法:

public ReentrantLock() {
    sync = new NonfairSync();
}

public ReentrantLock(boolean fair) {
    sync = fair ? new FairSync() : new NonfairSync();
}

在构造函数中,ReentrantLock随机选择了一种同步机制,即公平锁(FairSync)和非公平锁(NonfairSync)。这两种同步机制都是基于AQS(AbstractQueuedSynchronizer)实现的。

  • 公平锁(FairSync):采用先进先出的队列机制,将等待时间最长的线程先获取锁,从而保证了不产生饥饿现象。
  • 非公平锁(NonfairSync):直接将获取锁请求分配给任意一个等待线程。

上述两种机制各有优缺点,ReentrantLock结合实际情况进行选择。

锁的获取

在ReentrantLock中,锁的获取过程是通过调用lock()方法来实现的。我们来看一下NonfairSync的lock()方法实现:

final void lock() {
    if (compareAndSetState(0, 1))
        setExclusiveOwnerThread(Thread.currentThread());
    else
        acquire(1);
}

在上面的代码中,首先会对state值进行CAS操作,如果state的值为0,则当前线程获取到锁,并将state值设置为1;否则调用acquire()方法实现锁的获取。

在NonfairSync中,acquire()方法的实现如下:

final void acquire(int arg) {
    if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
        selfInterrupt();
}

该方法首先会调用tryAcquire()方法尝试获取锁。如果tryAcquire()返回false,则调用acquireQueued()方法将当前线程加入到等待队列中,并自旋等待获取锁。

如果当前线程成功获取锁,则会调用setExclusiveOwnerThread(Thread.currentThread())方法将当前线程设置为该锁的所有者。

需要注意的是,当一个线程尝试获取锁时如果失败了,则该线程不会立即被加入到等待队列中,而是会自旋一定的次数(默认是10次),然后重新尝试获取锁。这种方式可以有效地减少加入等待队列的线程数量,从而提高程序的性能。

锁的释放

在ReentrantLock中,锁的释放是通过调用unlock()方法来实现的。具体来说,我们来看一下NonfairSync的unlock()方法实现:

protected final boolean tryRelease(int releases) {
    int c = getState() - releases;
    if (Thread.currentThread() != getExclusiveOwnerThread())
        throw new IllegalMonitorStateException();
    boolean free = false;
    if (c == 0) {
        free = true;
        setExclusiveOwnerThread(null);
    }
    setState(c);
    return free;
}

public final void unlock() {
    release(1);
}

在上述代码中,ReentrantLock首先会调用tryRelease()方法来释放锁。如果当前线程并非该锁的所有者,则抛出IllegalMonitorStateException异常。如果当前线程成功释放了锁,则将该锁的所有者设置为null,并将state值更新为0。

需要注意的是,在调用unlock()方法释放锁时并没有使用synchronized关键字或者其他同步机制,而是通过调用tryRelease()方法来实现的。

小结

ReentrantLock是Java并发包下的一个基本类,它通过提供灵活的同步机制来保证线程安全。ReentrantLock的实现原理涉及到一些底

ReentrantLock可重入、可打断、锁超时实现原理 本文主要从使用到原理讲解了ReentrantLock锁的可重入、可打断和锁超时的特性,希望对大家有帮助。 阅读详情

相关推荐

源码解读 | Java中ReentrantLock的实现原理

本文将介绍Java中ReentrantLock的实现原理,从源码层面讲解公平锁和非公平锁的加锁、释放锁的流程,以及条件变量的实现。

字节幺零二四的博客 889

ReentrantLock 原理

调用 lock 方法,当为非公平锁时,只要有线程过来就尝试获取锁,如果获取成功AQS的state==0 并且CAS写入成功,将自身设置为独占锁的拥有者state!= 0 但当前独占锁就是自身(表示重入),将state累加;如果获取失败就将自己设置到 AQS 队列的尾部,等待唤醒;

小鲁蛋的博客 3438

ReentrantLock详解及实现

与synchronized不同,ReentrantLock允许多个线程同时获得锁,并且支持可重入特性,即同一个线程可以多次获取同一把锁。ReentrantLock还提供了一些其他的功能,例如条件变量(Condition),它可以帮助我们实现更复杂的线程通信和同步需求。条件变量可以和ReentrantLock配合使用,允许线程在特定条件满足之前等待,并在条件满足时被唤醒。在上面的示例中,我们创建了一个ReentrantLock实例,并在两个线程中使用该锁。在上面的示例中,我们使用了条件变量。

TechChamp的博客 272

java基础 - ReentrantLock

从结构上来看,AQS中有两个内部类,一个是Node结点类,一个是ConditionObject条件对象类,前者用来实现队列,后者用来做线程间通信。

软件测试入门笔记 3240

Java ReentrantLock 实现原理

谈到并发,不得不谈ReentrantLock;而谈到ReentrantLock,不得不谈AbstractQueuedSynchronizer(AQS)!类如其名,抽象的队列式的同步器,AQS定义了一套多线程访问共享资源的同步器框架,许多同步类实现都依赖于它,如常用的ReentrantLock/Semaphore/CountDownLatch…。它维护了一个volatile int state(代表共享资源)和一个FIFO线程等待队列(多线程争用资源被阻塞时会进入此队列)。

AI天才研究院 290

G2O (General Graph Optimization)入门及简单使用

g2o全称是General Graph Optimization,也就是图优化,我们在做SLAM后端或者更加常见的任何优化问题(曲线拟合)都可以使用G2O进行处理。

晓晨的博客 1万+

Java面试必备:Java中ReentrantLock的实现原理

ReentrantLock是Java并发包(java.util.concurrent.locks)中的一个可重入互斥锁实现,它提供了比synchronized关键字更灵活的锁机制,支持公平锁与非公平锁的选择、可中断的获取锁、超时获取锁等高级特性。

qq_58299462的博客 678

麒麟V10系统下CoreDump文件自动归档与快速定位指南(附coredumpctl实战)

本文详细介绍了在麒麟V10操作系统下,如何利用systemd-coredump机制和coredumpctl工具实现CoreDump文件的自动化管理与高效调试。内容涵盖从系统架构解析、自动化配置策略,到使用coredumpctl进行快速查询、过滤与深度分析的实战指南,旨在帮助运维人员和开发者快速定位系统崩溃的根本原因,提升问题排查效率。

gg901的博客 220

Java 中 ReentrantLock 的实现原理是什么?

类名作用:提供一个可重入的独占锁,同一线程可以多次获取锁(重入),但需要相应次数的释放。核心特性可重入(Reentrant):支持嵌套锁。可选择公平性(Fairness):支持公平锁和非公平锁。可中断:支持锁获取的中断响应。

qq_63553317的博客 976

Oracle19c时区升级实战:从32到42版本的数据泵TSTZ报错解决方案

本文详细介绍了Oracle19c时区版本从32升级到42的实战步骤,重点解决数据泵TSTZ报错问题。通过检查时区版本、下载补丁包、应用补丁及执行升级脚本等关键操作,确保数据库时区数据更新,避免夏令时转换错误和历史时区规则不匹配等问题。文章还提供了常见问题排查和升级后的注意事项,帮助DBA高效完成时区升级任务。

n7o8p的博客 282

MATLAB实战:5分钟搞定雷达信号分选SDIF算法(附完整源码下载)

本文详细介绍了如何在MATLAB中快速实现雷达信号分选的SDIF算法,通过序列差直方图统计高效识别脉冲重复间隔(PRI)。文章包含完整源码下载,从算法原理到实战调优技巧,帮助工程师在5分钟内掌握核心实现方法,显著提升雷达信号处理效率。

info6的博客 614

Java1.8 ReentrantLock加锁实现原理

主要是讲一下最近学习的情况目录前言一、ReentrantLock是什么?二、上锁过程1.实例化时可选锁类型2.加锁流程图3.非公平锁加锁流程源码分析4.公平锁加锁流程源码分析5.公平锁与非公平锁的区别6.Synchronized与Reentrantlock的区别。

DHG2012的博客 1537

用树莓派搭建全功能NAS服务器(01):树莓派基础操作&OMV搭建

写在前面 对于文件互传来说,局域网和云盘的操作总是独立的,而且很难将两者的优势合为一体。如果想要集多种优势为一体,那么NAS应该就是较为完美的解决方案了。 在这个系列中我们尽量跳过一些枯燥的理论知识,专注于说明两件事:   1.NAS是什么&能做什么 2.搭建思路&怎么做   这中间也会涉及到一些方案的选择,同类方案我也会列出来和大家分享我已知的优缺点,有兴趣可以多种尝试。(侧重于软件) 虽然是用树莓派搭建的,但是对于debian linux系统下的NAS搭建有着很好的参

斯塔克家的真维斯的工作间 2万+

java的reentrantlock_Java - 可重入锁ReentrantLock实现原理

Java - 可重入锁ReentrantLock实现原理在实现层面除了依赖于CAS(compareAndSet)方法之外,同时依赖于类LockSupport中的一些方法。一、LockSupport类 LockSupport 位于包 java.util.concurrent.locks ,其基本方法有public static void park()public static void parkNa...

weixin_34467247的博客 252

告别外置天线!手把手教你用HFSS仿真设计一个20x40mm的433MHz PCB蛇形天线

本文详细介绍了如何使用HFSS仿真工具设计一个20x40mm的433MHz PCB蛇形天线,解决物联网设备小型化中的天线集成难题。通过对比外置天线与PCB天线的性能差异,深入解析蛇形天线的电磁学原理,并提供从建模到优化的全流程实战指南,帮助工程师实现高效、低成本的微型化天线设计。

weixin_30606461的博客 430

【YOLOv11改进 - 特征融合】SDI:多层次特征融合模块,替换contact操作

【YOLOv11改进 - 特征融合】SDI:多层次特征融合模块,替换contact操作

专注于图像领域,主要研究内容包括计算机视觉和深度学习,特别是在图像分类、目标检测和图像生成等方面有深入的研究和实践经验。 1768

Java同步器之ReentrantLock锁的底层实现原理

Java里的锁有两大类,一类是synchronized锁,一类是concurrent包里的锁(JUC锁)。其中synchronized锁是JAVA语言层面提供的能力,在此不展开,本文主要讨论JUC里的ReentrantLock锁。ReentrantLock的lock()、unlock()等API其实依赖于内部的Synchronizer(注意,不是synchronized)来实现。Synchronizer又分为FairSync和NonfairSync,顾名思义是指公平和非公平。当调用ReentrantLock

l688899886的博客 510

070、人脸AE实战:基于人脸检测的亮度优先与背光补偿算法

本文分享了基于人脸检测的亮度优先与背光补偿算法的实战经验。针对逆光自拍场景下人脸过曝问题,作者提出了动态平衡方案: 通过内缩20%的人脸核心区域提取亮度,避免背景干扰 创新性地采用"亮度差+置信度"的背光判定机制 设计动态权重分配策略,人脸权重可在30%-70%间调整 引入平滑处理防止亮度跳变,补偿增益限制在1.5倍以内 关键点在于:不是简单提亮人脸,而是通过分析人脸与背景亮度差,在80-110目标亮度范围内动态调整,实现自然的人脸曝光效果。算法已在实际项目中验证,解决了传统AE在逆光场景下的失效问题。

zzfmlxs的博客 31

【Java第80集】java ReentrantLock底层实现原理详解

的核心实现依赖于 AQS,它是 Java 并发包中的基础框架,用于构建锁和同步器。state 变量表示锁的状态。state = 0:锁未被占用。state > 0:锁被占用,数值表示重入次数。等待队列(CLH 队列):维护等待锁的线程队列,遵循 FIFO 原则(公平锁)或允许插队(非公平锁)。的底层实现基于 AQS 框架,通过state变量管理锁状态,结合 CLH 队列实现线程排队。可重入性:通过 state 计数器实现。公平性选择:支持公平锁和非公平锁。高级功能。

学不可以已,活到老,学到老。 812

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

JAVA:ReentrantLock实现原理(附部分源码解析)

比如线程 A 已经获取了锁,在没释放的情况下再次调用。

weixin_45149504的博客 1183

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

深入理解 Java AQS 原理与 ReentrantLock 实现

AbstractQueuedSynchronizer(简称 AQS)是 Java 并发包(java.util.concurrent)中最核心的基础组件之一,它为 Java 中的大多数同步类(如 ReentrantLock、Semaphore、CountDownLatch 等)提供了一个通用的框架。理解 AQS 的工作原理对于深入掌握 Java 并发编程至关重要。AQS 的作用是解决同步器的实现问题,它将复杂的同步器实现分解为简单的框架方法,开发者只需要实现少量特定的方法就能快速构建出可靠的同步器。

weixin_40761387的博客 83

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

「Java」彻底掌握ReentrantLock实现原理

ReentrantLock主要利用CAS+CLH队列来实现。它支持公平锁和非公平锁,两者的实现类似。 CAS:Compare and Swap,比较并交换。CAS有3个操作数:内存值V、预期值A、要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做。该操作是一个原子操作,被广泛的应用在Java的底层实现中。在Java中,CAS主要是由sun.misc.Unsafe这个类通过JNI调用CPU底层指令实现。 CLH队列:带头结点的双向非循环链表(如下图所示):

你走过的路 风都是暖的 656

Java——ReentrantLock 实现原理

使用synchronized来做同步处理时,锁的获取和释放都是隐式的,实现的原理是通过编译后加上不同的机器指令来实现。 而ReentrantLock就是一个普通的类,它是基于AQS(AbstractQueuedSynchronizer)来实现的。 是一个重入锁:一个线程获得了锁之后仍然可以反复的加锁,不会出现自己阻塞自己的情况。 AQS是Java并发包里实现锁、同步的一个重...

Andy_zhouSir的博客 229

Java并发基石ReentrantLock:深入解读其原理与实现

也被称为“可重入锁”,是一个同步工具类,在java.util.concurrent.locks包下。这种锁的一个重要特点是,它允许一个线程多次获取同一个锁而不会产生死锁。这与关键字提供的锁定机制非常相似,但提供了更高的扩展性。的实现依赖于内部的Sync类,这个类是(AQS)的一个实现。AQS是Java并发库中许多同步工具(包括Semaphore和等)的核心。AQS使用一个int类型的变量来表示同步状态,用它来表示锁的持有计数和持有线程的信息。当计数为0时,表示锁未被任何线程持有。

weixin_44917365的博客 191
上一篇: Java中的volatile关键字实现原理
下一篇: Java中的synchronized关键字原理详解
JavaWizard-M
博客等级 码龄6年 3159粉丝 148原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值