Java 深度与实战 · 每日一读 :高频面试真题解析 · ReentrantLock / CAS / AQS 篇

news2025/4/28 8:07:48

ReentrantLock 深层分析:CAS、AQS原理全揭秘

此文为「Java 深度与实战·每日一读」系列第1篇,原创专栏,全篇不含水分,该系列整个面向:初学、进阶、面试、原理、实战,全综合型导向

目标:让任何级别的 Java 学习者,看不懂也要收藏,看得懂就能高速成长!

目录

  • ReentrantLock 深层分析:CAS、AQS原理全揭秘
    • @[toc](目录)
  • 一、基础矩阵:ReentrantLock 的概念
  • 二、CAS 原理完全解析
    • 2.1 CAS 是什么?
    • 2.2 CAS 实现原7406
    • 2.3 CAS 定位的问题:
  • 三、AQS 原理全揭秘
    • 3.1 AQS 是什么?
    • 3.2 AQS 工作流程
    • 3.3 AQS 的两种锁模式
  • 四、ReentrantLock 实现原理
    • 4.1 主要组成
    • 4.2 上锁流程
    • 4.3 重入的原理
  • 五、实战示例:体验一下经典场景
    • 5.1 例子:多线程清单操作
    • 5.2 例子:异常处理
  • 六、深层思考:ReentrantLock 比最原始的锁属性有什么优势?
  • 七、原理其实一点不难:简单就是最大的备考利器
  • 🗂️八、面试问题目录
    • 🔥 高频面试真题解析 · ReentrantLock / CAS / AQS 篇
      • 一、ReentrantLock 相关
        • 1. 什么是 ReentrantLock?与 synchronized 有什么区别?
        • 2. 为什么叫“可重入锁”?它如何实现可重入?
        • 3. ReentrantLock 支持哪些锁类型?怎么设置?
        • 4. 如何正确使用 ReentrantLock,避免死锁?
        • 5. tryLock 有什么应用场景?与 lock() 有什么不同?
        • 6. ReentrantLock 是怎么保证线程安全的?内部用到了哪些底层机制?
      • 二、CAS 相关
        • 1. CAS 原理是什么?CAS 操作是如何保证原子性的?
        • 2. CAS 操作失败会发生什么?什么是自旋?
        • 3. CAS 有哪些典型问题?如何解决 ABA 问题?
        • 4. CAS 和传统的加锁机制相比,有哪些优缺点?
      • 5. Java 中有哪些类用到了 CAS?
    • 三、AQS 相关
      • 1. 什么是 AQS?它在 Java 并发框架中起到了什么作用?
        • 2. AQS 的核心设计是什么?
      • 四、综合类问题(高频+进阶)
        • 1. 如何自己实现一个简单的可重入锁(MyLock)?
        • 2. 高并发场景下,什么时候使用 CAS?什么时候应该使用锁?
  • 🙏 感谢阅读!

一、基础矩阵:ReentrantLock 的概念

ReentrantLock(重入锁),是一种在 JDK1.5 引入的是符合 java.util.concurrent.locks.Lock 接口的实现类,它对 synchronized 进行了很多封装和扩展:

  • 可以手动锁 / 释放,更灵活
  • 支持多种锁(全局锁/全局重入锁)
  • 支持反应不同类型的等待(可不可为)

但是,其实现原理,非常高级!


二、CAS 原理完全解析

2.1 CAS 是什么?

CAS(Compare And Swap):比较并且替换。

通过 CPU 原定命令,把 目标内存地址的值预期值 比较,如果相等,则更新成新值;否则,不做操作。

操作是原定的,一步到位,避免线程竞争。

2.2 CAS 实现原7406

常见实现:

  • x86 系列 CPU :通过 cmpxchg
  • ARM 系列 CPU :使用 LDREX/STREX

JDK 中,主要通过 sun.misc.Unsafe 实现。

Unsafe.compareAndSwapInt(Object obj, long offset, int expect, int update)

2.3 CAS 定位的问题:

问题解决方案
ABA 问题AtomicStampedReference
自旋耗费 CPU合理控制自旋次数
不能操作多个值AtomicReference 或使用锁

三、AQS 原理全揭秘

3.1 AQS 是什么?

AbstractQueuedSynchronizer,抽象队列合并器

基于 FIFO 队列,提供一种构建高级合并器(如:ReentrantLock, CountDownLatch)的通用框架。

核心组件

  • state :锁的状态值(int)
  • CLH 队列 :线程坐标队列
  • Node :表示每个线程

3.2 AQS 工作流程

  1. CAS 抽奖默认拥有者权限
  2. 失败的线程进入队列排队等待
  3. 拥有者释放时,通知队头线程
  4. 队头线程重新挑战 CAS

图示:

线程A(锁住) -> 线程B(等待) -> 线稌C(等待)

它们就排成一条队。

3.3 AQS 的两种锁模式

  • 单种上锁(一个线程拥有)
  • 共享锁(多线程同时拥有,如 ReadWriteLock)

四、ReentrantLock 实现原理

4.1 主要组成

  • Sync:内部抽象类,继承 AQS
  • NonfairSync / FairSync:非公平和公平版本

4.2 上锁流程

  1. 尝试通过 CAS 拥有 state=1
  2. 失败:入队排队,等待
  3. 释放时,把 state=0,并 unpark 队头线程

4.3 重入的原理

同一线程再次上锁,state++,需要释放多次才能真正释放锁。


五、实战示例:体验一下经典场景

5.1 例子:多线程清单操作

Lock lock = new ReentrantLock();

public void clearCart() {
    lock.lock();
    try {
        // 清空购物车
        cart.clear();
    } finally {
        lock.unlock();
    }
}

5.2 例子:异常处理

必须放在 finally 中,否则导致泛锁,系统失效。


六、深层思考:ReentrantLock 比最原始的锁属性有什么优势?

方面synchronizedReentrantLock
解锁自动手动
应急中断不支持支持(lockInterruptibly)
时间等待不支持支持(tryLock)
公平性不保证可选公平

七、原理其实一点不难:简单就是最大的备考利器

只需记住:

  • CAS 保证原定性
  • AQS 通过队列来管理多个线程
  • ReentrantLock 给了更灵活的接口,更符合实际场景

🗂️八、面试问题目录

🔥 高频面试真题解析 · ReentrantLock / CAS / AQS 篇

点击直接跳转查看详细解析👇

  • 一、ReentrantLock 相关
    • 1. 什么是 ReentrantLock?与 synchronized 有什么区别?
    • 2. 为什么叫“可重入锁”?它如何实现可重入?
    • 3. ReentrantLock 支持哪些锁类型?怎么设置?
    • 4. 如何正确使用 ReentrantLock,避免死锁?
    • 5. tryLock 有什么应用场景?与 lock() 有什么不同?
    • 6. ReentrantLock 是怎么保证线程安全的?内部用到了哪些底层机制?
  • 二、CAS 相关
    • 1. CAS 原理是什么?CAS 操作是如何保证原子性的?
    • 2. CAS 操作失败会发生什么?什么是自旋?
    • 3. CAS 有哪些典型问题?如何解决 ABA 问题?
    • 4. CAS 和传统的加锁机制相比,有哪些优缺点?
    • 5. Java 中有哪些类用到了 CAS?
  • 三、AQS 相关
    • 1. 什么是 AQS?它在 Java 并发框架中起到了什么作用?
    • 2. AQS 的核心设计是什么?
    • 3. AQS 支持哪两种模式?分别有哪些代表性实现?
    • 4. AQS 如何实现线程挂起和唤醒?
    • 5. 如何基于 AQS 自定义一个同步器?
  • 四、综合类问题(高频+进阶)
    • 1. 如何自己实现一个简单的可重入锁(MyLock)?
    • 2. 高并发场景下,什么时候使用 CAS?什么时候应该使用锁?
    • 3. 公平锁和非公平锁的区别?使用场景?
    • 4. ReentrantLock 在高并发下会不会出现性能问题?原因是什么?
    • 5. synchronized、Lock、原子类三者怎么选?

一、ReentrantLock 相关

1. 什么是 ReentrantLock?与 synchronized 有什么区别?

ReentrantLock 是一种显式的锁机制,它属于 Java 的 java.util.concurrent 包,提供了比 synchronized 更强大的功能,如公平性设置、可中断等。

  • ReentrantLock 是可重入的,表示一个线程可以多次获取同一把锁,而不至于被自己阻塞。
  • 与 synchronized 区别:
    • ReentrantLock 支持 可中断锁,而 synchronized 不支持。
    • ReentrantLock 可以进行 公平性设置,确保锁被最久等待的线程先获得。
    • ReentrantLock 提供 tryLock() 方法,能设置锁的超时时间,而 synchronized 没有此功能。
2. 为什么叫“可重入锁”?它如何实现可重入?

“可重入”是指一个线程可以多次请求获取同一个锁,而不会发生死锁。线程再次请求时,不会被阻塞,直到线程释放锁。

  • 实现原理:
    • ReentrantLock 内部使用一个计数器来记录获取锁的次数,当前线程每获取一次锁,计数器加1。
    • 当计数器为0时,锁被释放。也就是说,锁的释放是通过计数器控制的。
3. ReentrantLock 支持哪些锁类型?怎么设置?

ReentrantLock 提供两种类型的锁:

  • 公平锁:线程获取锁的顺序为先到先得,适合任务对锁公平性要求较高的场景。
  • 非公平锁:线程获取锁的顺序不保证公平,适合大多数高性能场景。

可以通过 ReentrantLock(true) 设置公平锁,默认为非公平锁。

4. 如何正确使用 ReentrantLock,避免死锁?

死锁通常发生在多个线程相互持有锁且等待对方释放锁的场景。避免死锁的常见策略包括:

  • 避免锁嵌套:减少线程在持有锁的情况下进行其它操作。
  • 锁定顺序:确保多个线程获取多个锁时,锁的顺序一致。
5. tryLock 有什么应用场景?与 lock() 有什么不同?

tryLock() 方法可以设置超时来尝试获取锁,如果在规定时间内获取不到锁,返回 false

  • 应用场景:适用于尝试获取锁的操作,如果获取不到锁,可以继续执行其他任务。
  • 与 lock() 的区别lock() 是阻塞式的,一直等待获取锁;而 tryLock() 是非阻塞的,可以设置等待超时。
6. ReentrantLock 是怎么保证线程安全的?内部用到了哪些底层机制?

ReentrantLock 通过 AQS(AbstractQueuedSynchronizer) 框架实现线程安全。它通过 CAS(Compare And Swap) 技术实现原子操作,避免了竞争条件,并通过队列机制来管理等待线程。


二、CAS 相关

1. CAS 原理是什么?CAS 操作是如何保证原子性的?

CAS 是一种乐观锁机制,它通过比较内存中的值和预期值,如果相同,则更新为新值;如果不同,则不做任何操作。这样保证了多个线程并发执行时,只有一个线程能够成功更新。

  • 原子性保证:CAS 操作的原子性是由硬件支持的(如 CPU 中的原子指令)。
2. CAS 操作失败会发生什么?什么是自旋?
  • CAS 操作失败时,意味着有其他线程对目标变量进行了修改。此时,CAS 操作会重试,直到成功为止。
  • 自旋:CAS 失败后,会进入自旋状态,即线程不会被挂起,而是反复尝试执行 CAS 操作,直到成功或超时。
3. CAS 有哪些典型问题?如何解决 ABA 问题?
  • ABA 问题:在 CAS 操作中,检查到值从 A 变成 B 后,又变回 A,导致线程误以为值没有改变。
  • 解决方法:使用 版本号(即带时间戳的 CAS),通过额外的标记位来解决 ABA 问题。
4. CAS 和传统的加锁机制相比,有哪些优缺点?
  • 优点:CAS 操作不需要加锁,避免了线程上下文切换,提高了并发性能。
  • 缺点:CAS 会导致 ABA 问题,并且在长时间自旋的情况下,可能会导致 CPU 占用过高。

5. Java 中有哪些类用到了 CAS?

Java 中许多类使用 CAS 来优化性能,主要包括:

  • AtomicInteger
  • AtomicReference
  • ReentrantLock
  • ConcurrentLinkedQueue

三、AQS 相关

1. 什么是 AQS?它在 Java 并发框架中起到了什么作用?

AQS(AbstractQueuedSynchronizer)是 Java 提供的一个用于实现同步器的框架。它通过维护一个队列来管理请求同步的线程,从而实现锁、信号量等并发控制结构。

2. AQS 的核心设计是什么?

AQS 的核心设计是一个 FIFO(先入先出)队列,用来存储等待获取锁的线程。每个线程都通过 CAS 操作来尝试获取锁,成功的线程进入临界区,失败的线程进入等待队列。


四、综合类问题(高频+进阶)

1. 如何自己实现一个简单的可重入锁(MyLock)?
class MyLock {
    private int count = 0;
    private Thread currentThread = null;

    public synchronized void lock() {
        Thread thread = Thread.currentThread();
        while (currentThread != thread && count > 0) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        currentThread = thread;
        count++;
    }

    public synchronized void unlock() {
        if (Thread.currentThread() == currentThread) {
            count--;
            if (count == 0) {
                currentThread = null;
                notify();
            }
        }
    }
}
2. 高并发场景下,什么时候使用 CAS?什么时候应该使用锁?
  • 使用 CAS:适合无锁操作且对性能要求极高的场景,如计数器更新。
  • 使用锁:适用于有多个线程访问共享资源时,需要保证原子性和数据一致性,且数据量较大时使用锁更安全。

🙏 感谢阅读!

感谢大家阅读!如果你觉得这篇文章对你有所帮助,欢迎:
🔹 点赞
🔹 收藏
🔹 分享给更多需要的朋友

如果你有任何问题或者想深入讨论的内容,欢迎在评论区留言,或者私信我!你的每一条反馈都是我持续创作的动力!💪


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

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

相关文章

亚组风险比分析与可视化

1. 结果解读 1.1 风险比概述 1.1.1 风险比基本概念 风险比(Hazard Ratio)用于衡量治疗组与对照组事件发生的风险差异。 风险比为1,表示两组风险相同;小于1,治疗组风险低;大于1,治疗组风险高。 1.1.2 性别亚组分析 A性风险比小于1,表明治疗对A性有积极效果,风险降低。…

【博客系统】博客系统第一弹:博客系统项目配置、MyBatis-Plus 实现 Mapper 接口、处理项目公共模块:统一返回结果、统一异常处理

案例综合练习 - 博客系统 本节目标 从 0 到 1 完成博客系统后端项目的开发。 前言 通过前面课程的学习,我们掌握了 Spring 框架和 MyBatis 的基本使用,并完成了图书管理系统的常规功能开发。接下来我们系统地从 0 到 1 完成一个项目的开发。 项目介绍 …

基于OpenMV+STM32+OLED与YOLOv11+PaddleOCR的嵌入式车牌识别系统开发笔记

基于OpenMV、STM32与OLED的嵌入式车牌识别系统开发笔记 基于OpenMV、STM32与OLED的嵌入式车牌识别系统开发笔记系统架构全景 一、实物演示二、OpenMV端设计要点1. 硬件配置优化2. 智能帧率控制算法3. 数据传输协议设计 三、PyTorch后端核心实现:YOLOv11与PaddleOCR的…

w~嵌入式C语言~合集4

我自己的原文哦~ https://blog.51cto.com/whaosoft/13870376 一、STM32怎么选型 什么是 STM32 STM32,从字面上来理解,ST是意法半导体,M是Microelectronics的缩写,32表示32位,合起来理解,STM32就是指S…

K8S安全认证

一。用户认证的基本框架 在K8S集群中,客户端通常有两类: 1.User Account:一般独立于K8S之外的其他服务管理的用过户账号 2.Service Account:K8S管理的账号,用于为Pod中的服务进程在访问K8S提供身份标识 ApiServer是…

mybatis-plus里的com.baomidou.mybatisplus.core.override.MybatisMapperProxy 类的详细解析

以下是 com.baomidou.mybatisplus.core.override.MybatisMapperProxy 类的详细解析: 1. 类的作用 MybatisMapperProxy 是 MyBatis-Plus 框架中用于实现 Mapper 接口动态代理的核心类。它继承自 MyBatis 的 MapperProxy,并扩展了以下功能: …

在java程序中,类,进程,线程他们之间的关系以及main方法与他们之间的关系

在 Java 程序里,类、进程、线程各自有着不同的概念,同时也存在着紧密的联系,下面来详细分析它们之间的关系以及 main 方法和它们的关系。 类 类是 Java 中最基础的编程单元,是一种自定义的数据类型,它定义了对象的属…

[ACTF2020 新生赛]BackupFile题解

启动环境 进入后只有一段话,没有其他的说法。 解题方法 但是题目命名为backup file,应该是备份文件的意思,那么就用dirsearch工具来扫一下看看。 查看扫描结果 index.php.bak 下载下这个文件,查看文件内容。 进行php代码审计…

如何修改npm的全局安装路径?

修改 npm 的全局安装路径可以通过以下步骤完成,确保全局包(使用 -g 安装的模块)和缓存文件存储到自定义路径。以下是详细步骤: 1. 创建自定义路径的目录 在目标路径下创建两个文件夹,分别用于存储全局模块和缓存文件…

巧用 Element - UI 实现图片上传按钮的智能隐藏

引言 在前端开发中,使用 Element - UI 组件库来构建用户界面是非常常见的操作。其中图片上传功能更是在许多项目中频繁出现,比如用户头像上传、商品图片上传等场景。有时候,我们会有这样的需求:当上传图片达到一定数量后&#xf…

从“拼凑”到“构建”:大语言模型系统设计指南!

你有没有试过在没有说明书的情况下组装宜家家具?那种手忙脚乱却又充满期待的感觉,和设计大语言模型(LLM)系统时如出一辙。如果没有一个清晰的计划,很容易陷入混乱。我曾经也一头扎进去,满心期待却又手足无措,被网上那些复杂的架构图搞得晕头转向。于是,我坐下来,把它们…

【数据结构与算法】从完全二叉树到堆再到优先队列

完全二叉树 CBT 设二叉树的深度为 h , 若非最底层的其他各层的节点数都达到最大个数 , 最底层 h 的所有节点都连续集中在左侧的二叉树叫做 完全二叉树 . 特点 对任意节点 , 其右分支下的叶子节点的最底层为 L , 则其左分支下的叶子节点的最低层一定是 L 或 L 1 .完全二叉树…

【Linux网络】构建类似XShell功能的TCP服务器

📢博客主页:https://blog.csdn.net/2301_779549673 📢博客仓库:https://gitee.com/JohnKingW/linux_test/tree/master/lesson 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正! &…

Spring Boot 配置源详解(完整版)

Spring Boot 配置源详解(完整版) 一、配置源加载顺序与优先级 配置源类型优先级顺序(从高到低)对应配置类/接口是否可覆盖典型文件/来源命令行参数(--keyvalue)1(最高)SimpleComman…

puppeteer注入浏览器指纹过CDP

一、背景 通过puppeteer爬取目标网站时,经常会被对方网站检测到,比如原生puppeteerCDP特征非常明显,另外指纹如果一直不变,也会引发风控 二、实现 通过以下几行代码即可轻松过大部分检测点,并且能够切换指纹&#x…

软件项目实施全流程及交付物清单

需求分析 -> 概要设计 -> 详细设计 -> 开发实现 -> 测试 -> 部署 -> 运维 一、确认项目目标、范围和团队成员 二、收集和分析客户需求,确定需求规格 三、制定详细的项目计划,包括时间表、资源计划、预算 四、系统架构设计&#xf…

【2025计算机网络-面试常问】http和https区别是什么,http的内容有哪些,https用的是对称加密还是非对称加密,流程是怎么样的

HTTP与HTTPS全面对比及HTTPS加密流程详解 一、HTTP与HTTPS核心区别 特性HTTPHTTPS协议基础明文传输HTTP SSL/TLS加密层默认端口80443加密方式无加密混合加密(非对称对称)证书要求不需要需要CA颁发的数字证书安全性易被窃听、篡改、冒充防窃听、防篡改…

从梯度消失到百层网络:ResNet 是如何改变深度学习成为经典的?

自AlexNet赢得2012年ImageNet竞赛以来,每个新的获胜架构通常都会增加更多层数以降低错误率。一段时间内,增加层数确实有效,但随着网络深度的增加,深度学习中一个常见的问题——梯度消失或梯度爆炸开始出现。 梯度消失问题会导致梯…

Uni-App 多端电子合同开源项目介绍

项目概述 本项目是一款基于 uni-app框架开发的多端电子合同管理平台,旨在为企业及个人用户提供高效、安全、便捷的电子合同签署与管理服务。项目创新性地引入了 “证据链”与“非证据链”两种签署模式,满足不同场景下的签署需求,支持多种签署…