ReentrantLock原理及详细的使用方法

ReentrantLock详解(可重入、可中断、锁超时、公平锁、条件变量)、同步模式之顺序控制 文章目录1.ReentrantLock详解1.1 可重入1.2 可中断 lockInterruptibly()1.3 设置超时时间 tryLock()1.4 通过lock.tryLock()来解决, 哲学家就餐问题1.5 公平锁 new ReentrantLock(true)1.6 条件变量 Condition 1.ReentrantLock详解 相对于synchronized 它具备如下特点 可中断 可以设置超时时间 可以设置为公平锁 支持多个条件变量 与 synchronized 一样,都支持可重入 阅读详情
AI摘要

本文围绕Java并发编程中的可重入锁展开,介绍其基本原理,包括基于AQS实现、可重入性及公平与非公平锁;阐述详细使用方法,如基本使用、尝试获取锁等;分析内部实现机制;还给出使用注意事项,如手动释放锁、避免死锁等,提供更灵活的锁控制。

ReentrantLock 是 Java 并发编程中一种重要的同步机制,它比传统的 synchronized 提供了更高的灵活性和功能。下面将从 ReentrantLock 的基本原理、详细使用方法、内部实现机制、注意事项等方面详细说明。

一、ReentrantLock 的基本原理

ReentrantLock 是基于可重入的概念设计的锁。当一个线程已经获取了 ReentrantLock 锁,它可以再次进入该锁的同步代码块而不会陷入死锁。这是因为 ReentrantLock 记录了每个线程获取锁的次数,并允许同一线程多次获取它。线程获取锁的次数与释放锁的次数必须匹配,才能真正释放锁。

1.1 AQS(AbstractQueuedSynchronizer)

ReentrantLock 的核心是基于 AQS(抽象队列同步器)实现的。AQS 维护了一个队列,用于管理所有请求锁的线程。每个线程尝试获取锁时,如果当前锁被其他线程持有,则进入等待队列,阻塞等待锁释放。一旦锁释放,AQS 会从队列中唤醒下一个线程,允许它获取锁。

1.2 可重入性

可重入锁允许线程多次进入同一把锁。比如,一个递归方法可以在方法调用链中多次获取同一个锁而不导致死锁。这种特性主要依赖于线程独有的锁计数器。

1.3 公平锁与非公平锁
  • 公平锁:按照线程请求锁的顺序进行排队,先到先得。公平锁避免了线程“饥饿”,但性能可能比非公平锁稍低。
  • 非公平锁:线程直接尝试获取锁,不关心等待队列中的其他线程,可能会导致某些线程长期等待。非公平锁性能较高,因为它减少了上下文切换和线程调度的开销。

二、ReentrantLock 的详细使用方法

ReentrantLock 提供了比 synchronized 更多的控制能力,如尝试获取锁、可中断锁等待、锁的公平性等。下面逐一介绍其主要用法。

2.1 基本使用

在使用 ReentrantLock 时,通常遵循以下步骤:

  1. 创建锁对象:通过 new ReentrantLock() 创建锁实例。
  2. 获取锁:使用 lock() 或其他加锁方法获取锁。
  3. 执行临界区代码:在持有锁的情况下,执行需要保护的共享资源代码。
  4. 释放锁:使用 unlock() 释放锁,确保其他线程能够继续执行。
import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockDemo {

    private final ReentrantLock lock = new ReentrantLock(); // 创建锁
    private int counter = 0; // 共享资源

    public void increment() {
        lock.lock(); // 获取锁
        try {
            counter++;
            System.out.println(Thread.currentThread().getName() + " - Counter: " + counter);
        } finally {
            lock.unlock(); // 确保在 finally 中释放锁
        }
    }

    public static void main(String[] args) {
        ReentrantLockDemo demo = new ReentrantLockDemo();
        
        Thread t1 = new Thread(demo::increment);
        Thread t2 = new Thread(demo::increment);
        
        t1.start();
        t2.start();
    }
}
2.2 尝试获取锁

使用 tryLock() 可以尝试在不阻塞的情况下获取锁。如果当前锁未被持有,则立即获取并返回 true,否则返回 false。这种方法适合用于避免死锁。

if (lock.tryLock()) {
    try {
        // 执行临界区代码
    } finally {
        lock.unlock();
    }
} else {
    // 锁不可用时的处理逻辑
}

还可以设置超时时间来获取锁,避免线程长时间等待锁:

try {
    if (lock.tryLock(1, TimeUnit.SECONDS)) {
        try {
            // 获取锁后执行的逻辑
        } finally {
            lock.unlock();
        }
    } else {
        // 超时未能获取锁
    }
} catch (InterruptedException e) {
    e.printStackTrace();
}
2.3 可中断锁

lockInterruptibly() 允许线程在等待锁时响应中断。这对于实现中断操作的灵活性非常有用。

try {
    lock.lockInterruptibly(); // 可中断的锁获取
    try {
        // 临界区代码
    } finally {
        lock.unlock();
    }
} catch (InterruptedException e) {
    // 处理中断
    e.printStackTrace();
}
2.4 公平锁与非公平锁

通过构造函数选择锁的公平性:

  • 非公平锁(默认):

    ReentrantLock lock = new ReentrantLock();
    

  • 公平锁:

    ReentrantLock lock = new ReentrantLock(true);
    

公平锁保证线程按顺序获取锁,但性能较低;非公平锁可能导致“饥饿”,但性能更高。

三、ReentrantLock 的内部实现

ReentrantLock 基于 AQS 实现,它通过原子操作 CAS 来控制同步状态。AQS 维护了两个核心状态:

  1. state:表示锁的状态,0 表示未锁定,1 表示锁定。
  2. 线程队列:AQS 使用一个 FIFO 队列来管理等待锁的线程。

当线程尝试获取锁时:

  1. 如果 state == 0,线程成功获取锁,并将 state 设置为 1。
  2. 如果锁已经被持有(state != 0),线程进入等待队列,直到锁释放后被唤醒。

当持有锁的线程调用 unlock() 时,state 被递减。只有当 state 递减到 0 时,锁才真正释放。

四、使用 ReentrantLock 的注意事项

4.1 必须手动释放锁

ReentrantLock 和 synchronized 的主要区别之一是锁的释放必须显式调用 unlock()。忘记释放锁会导致其他线程永远无法获取锁。因此,通常在 try 块中获取锁,在 finally 块中释放锁,以确保异常情况下锁也能被正确释放。

4.2 避免死锁

当多个线程持有多个锁时,容易产生死锁问题。为了避免死锁,可以采用锁的超时机制,或者设计更合理的加锁顺序。

4.3 性能与公平性

非公平锁的性能比公平锁更好,但可能导致某些线程长期无法获得锁。公平锁避免了这种情况,但每次加锁和解锁的性能稍差。在高并发场景下,通常选择非公平锁来提升性能。

4.4 避免锁竞争

过度使用锁可能导致线程竞争和性能下降。在设计多线程应用时,尽量减少临界区的长度,避免不必要的锁。

五、总结

ReentrantLock 提供了比 synchronized 更灵活的锁控制方式。它可以:

  • 选择公平锁和非公平锁;
  • 提供尝试获取锁和可中断的锁;
  • 允许锁的重入;
  • 支持手动加锁和解锁的细粒度控制。
多线程系列(八) -ReentrantLock基本用法介绍 在之前的线程系列文章中,我们介绍到了使用synchronized关键字可以实现线程同步安全的效果,以及采用wait()、notify()和notifyAll()方法,可以实现多个线程之间的通信协调,基本可以满足并发编程的需求。 阅读详情

相关推荐

多线程系列(九) -ReentrantLock常用方法详解

在上一篇文章中,我们介绍了ReentrantLock类的一些基本用法,今天我们重点来介绍一下ReentrantLock其它的常用方法,以便对ReentrantLock类的使用有更深入的理解。

程序员志哥的博客 2352

ReentrantLock详解

ReentrantLock使用,

weixin_56738054的博客 1万+

【多线程】轻松彻底搞懂ReentrantLock的底层实现原理

上篇博客讲解了Sychronized的底层实现原理,它是基于jdk实现的,现在此篇博客讲解基于AQS 框架实现的另一个锁ReentrantLock。

李光 未来科技 1665

ReentrantLock锁

1. 简介 ReentrantLock,可重入锁,是一种递归无阻塞的同步机制。它可以等同于 synchronized 的使用,但是 ReentrantLock 提供了比 synchronized 更强大、灵活的锁机制,可以减少死锁发生的概率

weixin_46121031的博客 7641

Unity游戏开发实战:手把手教你用C#实现一个简单的反向运动学(IK)控制器

本文详细介绍了在Unity游戏开发中如何使用C#实现一个简单的反向运动学(IK)控制器。通过建立骨骼层级结构、实现CCD算法和角度限制,开发者可以轻松创建自然的角色动画效果。文章还提供了可视化调试工具和性能优化方案,帮助提升开发效率。

weixin_42523711的博客 244

IMU660RA姿态解算实战:从传感器滤波到欧拉角输出的完整实现

本文详细介绍了IMU660RA姿态解算的完整实现过程,从传感器滤波到欧拉角输出。通过实战案例和代码示例,展示了如何有效处理陀螺仪和加速度计的噪声问题,并选择合适的算法进行数据融合和姿态解算。特别强调了欧拉角输出中的坐标系对齐和动态补偿技巧,帮助工程师快速掌握IMU660RA的应用。

weixin_42524762的博客 386

方法实现原理_ReentrantLock 原理分析(一)

ReentrantLock 作用ReentrantLock 是一把可重入的排它锁。多线程下,可以保证只有一个线程获取该锁,如果该线程已经获取锁,并且重新尝试获取该锁是可以成功获取的,这就是可重入的概念。他主要用途就是为共享资源提供同步访问的作用。ReentrantLock 使用例子使用方法也很简单,new 一个ReentrantLock 实例,然后掉用lock方法获取锁,使用完毕调用unlock方...

weixin_35054319的博客 217

经典损失函数——均方误差(MSE)和交叉熵误差(CEE)的python实现

损失函数(loss function)用来表示当前的神经网络对训练数据不拟合的程度。这个损失函数有很多,但是一般使用均方误差和交叉熵误差等。 1.均方误差(mean squared error) 先来看一下表达式: 用于将的求导结果变成,是神经网络的输出,是训练数据的标签值,k表示数据的维度。 用python实现: def MS...

Answer3664的博客 1万+

【并发编程】深入理解ReentrantLock使用方法与原理解析(1)

ReentrantLock是Java多线程编程中一款强大的同步工具,具备可重入、公平非公平锁等特性,为多线程程序提供了高度灵活性。深入理解其使用方法和底层原理有助于编写高效、安全的多线程应用。在实际项目中,根据需求选择适当的锁策略,能够更好地发挥ReentrantLock的优势。通过遵循相关指南,可以安全地使用ReentrantLock,避免一些潜在陷阱。在实际应用中,依赖于精心设计和对多线程问题的深刻理解,才能最大程度地发挥ReentrantLock的潜力,帮助读者编写高效、可靠的多线程程序。

龚小帅的博客 1630

别再死记硬背窗函数公式了!用MATLAB实战汉宁窗FIR滤波器,从频谱图看懂‘主瓣’和‘旁瓣’

本文通过MATLAB实战演示汉宁窗FIR滤波器的设计过程,帮助读者从频谱图直观理解主瓣与旁瓣的特性。文章详细对比了矩形窗与汉宁窗的频谱差异,并提供了高通滤波器设计的完整代码示例,适用于数字信号处理学习和工程应用。

weixin_30555125的博客 490

【第24例】华为 IPD 体系 | RMT 需求管理团队

RMT需求管理团队

产品线负责人 1765

java锁机制(CAS/synchronize/ReentrantLock)的实现原理和使用方法

CAS/synchronized锁/自旋锁

网络安全研究 1684

RK3588平台开发系列讲解(项目篇)常见模型结构

📢 AI 模型常采用人工神经网络来模拟人脑神经的记忆和处理信号的能力。常见的人工神经网络类型有深度神经网络(Deep Neural Network,DNN)、卷积神经网络(Convolutional Neural Network,CNN)、循环神经网络(Recurrent Neural Network,RNN)等。

内核笔记 1759

同步方法中的锁对象_ReentrantLock 中 锁和解锁的底层原理浅析

关于 ReentrantLock 中锁 lock() 和解锁 unlock() 的底层原理浅析如下代码,当我们在使用 ReentrantLock 进行加锁和解锁时,底层到底是如何帮助我们进行控制的啦? static Lock lock = new ReentrantLock(); public static void main(String[] args) { // 使用...

weixin_34640046的博客 520

【ArcGIS微课1000例】0149:Geographic Imager6.6下载安装教程

首先保证电脑上安装对应版本的PS软件,笔者安装的是PS2023(V24.7)版本,然后安装本软件。保持以上窗口运行状态,然后打开PS,自动弹出如下窗口。勾选【Automatically checkout LIcense】,点击Close。双击setup开始安装,点击【确认】,一路默认安装到底。驱动器:DVD-ROM驱动器(用于DVD版本)处理器:2GHz或更快的英特尔或AMD处理器。安装完成后,将Crack中的所有文件拷贝到。硬盘:600 MB的可用硬盘空间用于安装。内存:4GB内存(建议8GB或更高)。

智慧空间实验室 1219

AI Agent在智能腰带中的姿势矫正与提醒

随着人们生活方式的改变,长时间不正确的坐姿、站姿等不良姿势问题日益普遍,这不仅会导致身体疲劳,还可能引发颈椎病、腰椎病等多种健康问题。智能腰带作为一种可穿戴设备,具有实时监测人体姿势的潜力。本研究的目的是将AI Agent引入智能腰带,实现对人体姿势的准确识别、矫正与提醒功能。本研究的范围涵盖了从AI Agent的核心算法原理到智能腰带的实际开发与应用。包括传感器数据的采集与处理、机器学习算法的选择与训练、智能腰带的硬件设计与软件开发,以及在不同场景下的实际应用测试。本文共分为十个部分。

AI 原生应用开发的博客 344

【Java核心能力】上万字 ReentrantLock 原理全面详解!

本来写这篇文章是因为自己对 ReentrantLock 的了解一直都比较表面,原理了解的还不是那么的清楚,并且对 AQS 也都是一知半解,但是在面试中这些都是比较常问的内容,如果原理了解比较清楚的话,对面试会有很大的帮助,因此自己在这里也总结了一份,本来以为很快就写完了,没想到竟然写了两天,文字的话就有 6000 +,ReentrantLock 中大部分的内容也都说到了,并且配有许多图片,如果感觉内容太多的话,可以对 ReentrantLock 中加锁以及解锁内容重点阅读,希望对你有所帮助!

qq_45260619的博客 2079

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

ReentrantLock实现原理深入探究

前言 这篇文章被归到Java基础分类中,其实真的一点都不基础。网上写ReentrantLock的使用、ReentrantLock和synchronized的区别的文章很多,研究ReentrantLock并且能讲清楚ReentrantLock的原理的文章很少,本文就来研究一下ReentrantLock的实现原理。研究ReentrantLock的实现原理需要比较好的Java基础以及阅读代码的能...

cnq2328的专栏 317

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

synchronized 和 reentrantlock 区别是什么_synchronized关键字和Lock锁有什么区别

一道非常经典的面试题了,好多次都遇到过,根据这个可以衍生很多其它的面试点,大家也可扩散下思维。实现的原理不同synchronized是关键字,属于JVM层面,是基于Monitor对象实现的同步,每次对锁的获取与释放会带来用户态和内核态之间的切换,非常影响性能,在并发量较高的时候,synchronized性能不高。JDK1.6之后有优化。从JDK1.5,并发包引入Lock锁Lock锁是基于API层面...

weixin_39644139的博客 289

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

关于 ReentrantLock 中锁 lock() 和解锁 unlock() 的底层原理浅析

当我们在使用 ReentrantLock 进行加锁和解锁时,底层到底是如何帮助我们进行控制的啦?带着这样的疑问,我们先后跟进 lock()和unlock() 源码一探究竟。

yanzigejuly的博客 1113

ReentrantLock使用和原理(AQS简述)

在开发过程中,synchronized是最简单的同步控制方法,在通常情况下是够用的,但synchronized时不响应中断,而且有时候,我们需要灵活的来控制加解锁。这时候可以使用ReentrantLock。 在以前的版本中,synchronized效率是远远低于ReentrantLock,后来经过优化,两者性能差距不大了。但ReentrantLock有一些新特性,是synchronized所不具...

永远向前 1503

Java之Reentrantlock的实现及AQS的原理和应用

ReentrantLock意思为可重入锁,指的是一个线程能够对一个临界资源重复加锁。

qq_62592925的博客 1450

Java-ReentrantLock基本使用及底层原理

概述 ReentrantLock相对于synchronized有一下特性: 1:可中断 2:可设置超时时间 3:可设置为公平锁 4:可设置多个条件变量 与synchronized相同的是:都是支持可重入。 可重入 可重入是指一个线程在获得一把锁后,因为它是这把锁的拥有这,所以有权利再次获得这把锁。 但是不可重入是指,线程获得锁后再次想获得锁但是被挡住了! 示例:让主线程连续获得method1...

qq_42411214的博客 1015

从ReentrantLock的实现看AQS的原理及应用

前言 Java中的大部分同步类(Lock、Semaphore、ReentrantLock等)都是基于AbstractQueuedSynchronizer(简称为AQS)实现的。AQS是一种提供了原子式管理同步状态、阻塞和唤醒线程功能以及队列模型的简单框架。本文会从应用层逐渐深入到原理层,并通过ReentrantLock的基本特性和ReentrantLock与AQS的关联,来深入解读AQS相关独占锁的知识点,同时采取问答的模式来帮助大家理解AQS。由于篇幅原因,本篇文章主要阐述AQS中独占锁的逻辑和Sync

上山打卤面的博客 517

Java:Java学习笔记之ReentrantLock的简单理解和使用

ReentrantLock ReentrantLock1、相关知识1.1 公平锁和非公平锁1.2 可重入锁1.3、CAS算法2、背景、定义和特征2.1、背景2.2、定义2.3、特征3、基本结构4、基本使用4.1、解决背景问题4.2、重入锁 使用4.3、公平锁使用5、源码分析5.1、AQS5.2、非公平锁的实现原理5.2.1、lock方法获取锁:tryAcquire5.2.2、锁的释放:tryRelease5.3、公平锁的实现原理5.3.1、lock方法获取锁:tryAcquire5.3.2、锁的释放:try

JMW1407的博客 6990
上一篇: MySQL 的 MVCC机制
下一篇: ReentrantLock 和synchronize比较
yymagicer
博客等级 码龄13年 1425粉丝 180原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yymagicer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值