Java并发编程:全面解析锁策略、CAS与synchronized优化机制

news2025/6/8 8:11:15

一、六种锁策略场景化解析

1. 乐观锁 vs 悲观锁:图书馆借书的两种策略

核心差异:对资源是否会被抢占的预期不同。

  • 乐观锁(假设冲突概率低)
    → 行为:直接去书架上拿书(围绕加锁要做的工作更少)。
    → 风险:可能发现书已被借走(需要重试)。
// 伪代码实现:类似检查版本号
if (当前书未被借) {
    借书成功;
} else {
    重新查询;
}
  • 悲观锁(假设冲突概率高)
    → 行为:先预定书籍再取书(围绕加锁要做的工作更多)。
    → 保障:确保拿到书时没人争抢。
// 伪代码实现:类似直接加锁
lock(书籍);
借书操作;
unlock(书籍);

2. 轻量级锁 vs 重量级锁:开锁的两种方式

对比维度轻量级锁(密码锁)重量级锁(管理员钥匙)
开锁速度快(直接输入密码)慢(需找管理员申请)
适用场景短暂使用(如储物柜)长期占用(如保险箱)
资源消耗低(自行操作)高(依赖第三方)

3. 自旋锁 vs 挂起等待锁:等电梯的两种策略

  • 自旋锁:属于乐观锁/轻量级锁的一种典型表现。会忙等:等待过程中不会释放cpu资源,一旦锁释放就立即有机会拿到锁。
  • 挂起等待锁:属于悲观锁/重量级锁的一种典型表现。不忙等:让出了cpu资源,锁释放后不确定什么时候去拿锁。

4. 公平锁 vs 非公平锁:排队的两种规则

  • 公平锁:像银行叫号机,先到先得(需要额外的操作,引入队列时需要记录每个加锁的顺序)。
  • 非公平锁:像地铁抢座位,谁快谁得(不需要额外操作,概率均等的让线程去占用锁)。

5. 可重入锁 vs 不可重入锁

核心差异:同一线程能否重复获取同一把锁。

类型行为表现代码示例结果
不可重入锁同一线程重复加锁会死锁lock(); lock();永久阻塞
可重入锁允许同一线程多次加锁synchronized void a() { b(); }正常执行
synchronized void b() {}

可重入锁三要素

  1. 记录持有线程:标记当前锁的归属者。
  2. 身份验证:新请求的线程需匹配持有者。
  3. 计时器管理
    • 加锁时 +1,解锁时 -1
    • 归零时真正释放锁。

6. 读写锁:图书馆的管理规划

ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();

// 读者线程
rwLock.readLock().lock();  // 多个读者可同时进入
try {
    // 读操作
} finally {
    rwLock.readLock().unlock();
}

// 写者线程
rwLock.writeLock().lock(); // 只允许一个写者进入
try {
    // 写操作
} finally {
    rwLock.writeLock().unlock();
}

二、synchronized锁升级过程详解

状态流转示意图(该过程不可逆)

各阶段特征

  1. 偏向锁(占座模式)
    • 第一个线程来时做个标记(类似在座位上放本书)。
    • 没有真实加锁开销,延迟真正的锁操作。
  2. 轻量级锁(智能转圈)
    • 自适应自旋:JVM动态判断转圈次数(类似智能交通信号灯)。
    • 若最近频繁抢到锁 → 允许多转几圈。
    • 多次失败 → 快速放弃转圈。
    • 高效场景:适合抢锁时间 < 线程切换时间(约1μs)。
  3. 重量级锁(系统调度)
    • 管理员介入:操作系统维护阻塞队列
    • 释放CPU:线程挂起不消耗CPU资源。
    • 恢复延迟:唤醒线程需上下文切换(约10-20μs)。

关键机制图解


三、编译器优化策略

1. 锁消除:去掉多余的锁

public String concat(String s1, String s2) {
    Object lock = new Object(); // 局部对象不可能被共享
    synchronized(lock) {        // 被编译器优化删除
        return s1 + s2;
    }
}

2. 锁粗化:合并相邻的锁

a. 锁粒度定义

锁粒度:指 synchronized 代码块内包含的代码量。

  • 细粒度锁:代码量少,加锁范围小(如只包裹一行代码)。
  • 粗粒度锁:代码量大,加锁范围广(如包裹整个方法)。
// 细粒度锁示例(不推荐)
public void process() {
    synchronized(this) { step1(); } // 频繁加解锁
    // 其他代码...
    synchronized(this) { step2(); }
}

// 粗粒度锁示例(推荐)
public void process() {
    synchronized(this) { // 合并为单次加锁
        step1();
        // 其他代码...
        step2();
    }
}

b. 锁粗化(Lock Coarsening)工作原理

优化触发条件

  • 检测到连续相邻的同步块。
  • 锁对象相同且无中间非同步代码。
  • JIT编译器判定合并后不会显著增加竞争概率

四、CAS机制详解

1. 核心原理:自动售货机式操作

比喻说明
CAS操作如同使用自动售货机购买商品:

  1. 查看标价(读取内存值)
  2. 投入硬币(准备新值)
  3. 校验标价(比较内存值)
  4. 出货取货(原子性更新)

    说明alt 关键字在此处表示条件分支,相当于 if

2. 硬件级原子性保障

; x86架构实现(CMPXCHG指令)
lock cmpxchg [mem], new_val
; lock前缀锁定总线,保证多核环境原子性
; 比较并交换:若[mem]==EAX寄存器值,则[mem]=new_val

3. CAS具体使用场景

实现原子类

private static AtomicInteger count = new AtomicInteger(0);

void increment() {
    int oldVal, newVal;
    do {
        oldVal = count.get();    // ① 读取当前值
        newVal = oldVal + 1;     // ② 计算新值
    } while (!count.compareAndSet(oldVal, newVal)); // ③ CAS更新
}

// 线程安全原理:
// 假设线程A和B同时执行到③:
// - A先执行CAS成功,将0→1
// - B执行CAS时发现当前值≠oldVal(0),循环重试

实现自旋锁

public class SpinLock {
    private AtomicBoolean locked = new AtomicBoolean(false);

    // 获取锁
    public void lock() {
        while (!locked.compareAndSet(false, true)) { // CAS自旋
            Thread.yield(); // 让出CPU时间片避免过度消耗
        }
    }

    // 释放锁
    public void unlock() {
        locked.set(false);
    }
}

运行场景分析

线程行为锁状态变化结果
线程A获取锁locked: false → true成功,进入临界区
线程B尝试获取锁检测到 locked = true自旋等待
线程A释放锁locked: true → false线程B CAS成功

4. ABA问题深度剖析:重复转账漏洞

场景描述
张三的银行卡余额为1000元,当他尝试向他人转账500元时,由于网络延迟连续触发了两次转账请求(线程1和线程2)。与此同时,李四向张三账户转入500元(线程3),三个线程的交错执行将导致以下危险操作流:

问题本质

  • 值回退欺骗:CAS机制仅检查当前值是否等于预期值(1000元),无法感知中间发生了 1000→500→1000隐形状态变化
  • 资金损失:最终账户余额为500元(正确应为1000-500+500=1000元),张三实际被重复扣款1000元

版本号解决方案
通过版本号递增标记数据状态变化,即使值相同也能识别中间修改。

// 账户状态(版本号 + 余额)
AtomicStampedReference<Integer> account = 
    new AtomicStampedReference<>(1000, 0); // 初始值1000元,版本0

void transfer(int amount) {
    int[] stampHolder = new int[1];
    int oldValue = account.get(stampHolder); // 同时获取值和版本号
    int newValue = oldValue - amount;
    
    // 核心逻辑(适配为Java标准API)
    if (!account.compareAndSet(
            oldValue,         // 期望值
            newValue,         // 新值
            stampHolder[0],   // 期望版本号
            stampHolder[0] + 1 // 新版本号(必须递增)
    )) {
        System.out.println("转账失败:数据已被修改");
    } else {
        System.out.println("转账成功");
    }
}

关键机制拆解

  1. 版本号必须递增
stampHolder[0] + 1  // 新版本号必须 > 旧版本号
  • 不可逆性:版本号只能增加(类似流水号),确保状态变化的唯一标识
  • 防伪造:阻止恶意或错误的状态回滚(如黑客尝试恢复旧数据)。
  1. 原子性双重检查
compareAndSet(oldValue, newValue, oldVersion, newVersion)
  • 同时校验:值是否变化 + 版本号是否匹配。
  • 操作原子性:整个检查-更新过程不可分割。

    结果
  • 线程1的转账操作因版本号不匹配被拒绝。
  • 最终余额正确为1000元(500转出 + 500转入)。

五、总结

本文系统解析Java并发编程核心机制:

  1. 六大锁策略:涵盖乐观锁与悲观锁、轻量级锁与重量级锁、自旋锁与挂起等待锁、公平锁与非公平锁、可重入锁、读写锁的适用场景及实现原理。
  2. synchronized优化:通过偏向锁→轻量级锁→重量级锁的升级过程实现性能自适应。
  3. 编译器优化:锁消除与锁粗化技术减少不必要的同步开销。
  4. CAS机制:详解原子操作原理、自旋锁实现,以及ABA问题的版本号解决方案。

结语

并发世界如同繁忙的十字路口,锁策略是交通信号灯,CAS是智能感应器,而开发者就是城市交通规划师。只有深刻理解每项机制的设计哲学,才能让数据流如同车流般高效畅通——既不会因过度控制导致拥堵,也不会因管理松散引发事故。记住:最好的并发程序不是最快的那一个,而是在正确性与性能间找到最优平衡的那一个

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

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

相关文章

2025第三届黄河流域网络安全技能挑战赛--Crypto--WriteUp

2025第三届黄河流域网络安全技能挑战赛–Crypto–WriteUp Crypto sandwitch task from Crypto.Util.number import * import gmpy2 flag bflag{fake_flag} assert len(flag) 39 p getPrime(512) q getPrime(512) n p * q e 0x3 pad1 beasy_problem pad2 bHow_to_so…

[爬虫知识] IP代理

相关实战案例&#xff1a;[爬虫实战] 代理爬取&#xff1a;小白也能看懂怎么用代理 相关爬虫专栏&#xff1a;JS逆向爬虫实战 爬虫知识点合集 爬虫实战案例 引言&#xff1a;爬虫与IP封锁的攻防战 对网络爬虫而言&#xff0c;遇到的一个较棘手的问题就是封IP&#xff1a;请…

6个月Python学习计划 Day 1 - Python 基础入门 开发环境搭建

6个月Python学习计划&#xff1a;从入门到AI实战&#xff08;前端开发者进阶指南&#xff09; &#x1f3af; 今日目标 理解 Python 的背景和用途安装 Python 开发环境熟悉基本语法&#xff1a;变量、数据类型、打印输出动手编写第一个 Python 程序 &#x1f9e0; 学习内容详…

GraphPad Prism工作表的基本操作

《2025新书现货 GraphPad Prism图表可视化与统计数据分析&#xff08;视频教学版&#xff09;雍杨 康巧昆 清华大学出版社教材书籍 9787302686460 GraphPadPrism图表可视化 无规格》【摘要 书评 试读】- 京东图书 GraphPad Prism中包含5种工作表&#xff0c;每种工作表的基本操…

成年后还能学习多少知识,由大脑的这个数量决定

撰文&#xff5c;Anne Trafton 编译&#xff5c;郑添惺 审校&#xff5c;clefable 麻省理工学院&#xff08;MIT&#xff09;的一些神经科学家发现&#xff0c;成年的大脑中含有数百万个“静默突触”&#xff08;silent synapses&#xff09;。它们是神经元之间未成熟的神经突…

MySQL连接错误解决方案:Can‘t connect to MySQL server on ‘localhost‘ (10038)

错误描述 当您尝试连接MySQL数据库时&#xff0c;可能会遇到以下错误提示&#xff1a; 这个错误表明客户端无法连接到本地MySQL服务器。 可能的原因 MySQL服务未启动 MySQL配置问题 防火墙或安全软件阻止连接 端口被占用或未正确配置 网络连接问题 解决方案 方法一&am…

CSS相关知识

1.清除浮动的方法 2.定位 静态定位相当于标准流 相对定位不脱离文档流&#xff0c;仍然占据原来的位置&#xff08;最频繁的作用是给绝对定位当爹&#xff09; 绝对定位脱离文档标准流&#xff0c;不再占有原来位置 3.BFC 1. 解决浮动元素导致的父容器高度塌陷 2. 阻止相邻元…

AI扫描王APP:高效便捷的手机扫描工具,让生活更智能

AI扫描王APP是一款功能强大的手机扫描软件&#xff0c;专为追求高效、便捷的用户设计。它不仅支持文字提取和扫描翻译&#xff0c;还能进行测量&#xff0c;满足用户在不同场景下的需求。无论是办公、学习还是日常使用&#xff0c;AI扫描王都能帮助你快速完成任务&#xff0c;节…

《仿盒马》app开发技术分享-- 原生地图展示(端云一体)

开发准备 上一节我们实现了获取当前用户的位置&#xff0c;并且成功的拿到了经纬度&#xff0c;这一节我们就要根据拿到的经纬度&#xff0c;结合我们其他的知识点来实现地图的展示。 功能分析 地图的展示&#xff0c;我们需要在管理中心先给我们对应的应用开启地图api功能&…

IP、子网掩码、默认网关、DNS

IP、子网掩码、默认网关、DNS 1. 概述1.1 windows配置处 2.IP 地址&#xff08;Internet Protocol Address&#xff09;2.1 公网ip2.2 内网ip2.3 &#x1f310; 公网 IP 与内网 IP 的关系&#xff08;NAT&#xff09; 3. 子网掩码&#xff08;Subnet Mask&#xff09;4. 默认网…

华为OD机试真题——字符串加密 (2025B卷:100分)Java/python/JavaScript/C/C++/GO最佳实现

2025 B卷 100分 题型 本专栏内全部题目均提供Java、python、JavaScript、C、C++、GO六种语言的最佳实现方式; 并且每种语言均涵盖详细的问题分析、解题思路、代码实现、代码详解、3个测试用例以及综合分析; 本文收录于专栏:《2025华为OD真题目录+全流程解析+备考攻略+经验分…

角度回归——八参数检测四边形Gliding Vertex

文章目录 一、介绍&#xff08;一&#xff09;五参数检测方法&#xff08; 基于角度&#xff09;&#xff08;二&#xff09;八参数检测方法&#xff08;point-based&#xff09;的边界 二、方案分析&#xff08;一&#xff09;问题定义&#xff08;二&#xff09;方案&#xf…

AI助力,制作视频裁剪软件

1. 视频裁剪软件套路多 最近再做一些测试&#xff0c;经常需要录屏什么的&#xff0c;有时候录制的时长视频&#xff0c;需要裁剪&#xff0c;比如去掉开头一些帧或者结尾的一些帧&#xff0c;就想保留关键点。但是网上下的一些软件&#xff0c;打开一用都是要付费的。所以想着…

[实战]用户系统-2-完善登录和校验以及VIP

这里写目录标题 完善登录和校验新建lib-auth创建配置引入配置和JWT完善登录基本登录单点登录多点登录校验和拦截编写守卫编写装饰器使用完善VIP修改mysql模型编写vip守卫代码进度完善登录和校验 之前我们模拟过用户的登录,本节将实现token的生成,校验,redis做黑名单。我们需…

印度语言指令驱动的无人机导航!UAV-VLN:端到端视觉语言导航助力无人机自主飞行

作者&#xff1a;Pranav Saxena, Nishant Raghuvanshi and Neena Goveas单位&#xff1a;比尔拉理工学院&#xff08;戈瓦校区&#xff09;论文标题&#xff1a;UAV-VLN: End-to-End Vision Language guided Navigation for UAVs论文链接&#xff1a;https://arxiv.org/pdf/250…

mysql都有哪些锁?

MySQL中的锁机制是确保数据库并发操作正确性和一致性的重要组成部分&#xff0c;根据锁的粒度、用途和特性&#xff0c;可以分为多种类型。以下是MySQL中常见的锁及其详细说明&#xff1a; 一、按锁的粒度划分 行级锁&#xff08;Row-level Locks&#xff09; 描述&#xff1a;…

HarmonyOS NEXT 使用 relationalStore 实现数据库操作

大家好&#xff0c;我是V哥。在 HarmonyOS NEXT 开发中&#xff0c;如何操作数据库&#xff0c;V 哥在测试中总结了以下学习代码&#xff0c;分享给你&#xff0c;如何想要系统学习鸿蒙开发&#xff0c;可以了解一下 V 哥最近刚刚上架出版的 《HarmonyOS 鸿蒙开发之路 卷2 从入…

R语言学习--Day04--数据分析技巧

在清洗完数据&#xff0c;在对数据分析前&#xff0c;我们要懂得先梳理一下我们的逻辑&#xff0c;即数据是什么形式的&#xff0c;要进行哪种分析&#xff0c;有可能呈现什么特点&#xff0c;进而再想怎么处理数据去画图可以最大程度地凸显我们要的特点。 一般来讲&#xff0…

SRS流媒体服务器之RTC播放环境搭建

环境概述 srs版本 commit 44f0c36b61bc7c3a1d51cb60be0ec184c840f09d Author: winlin <winlinvip.126.com> Date: Wed Aug 2 10:34:41 2023 0800Release v4.0-r5, 4.0 release5, v4.0.271, 145574 lines. rtc.conf # WebRTC streaming config for SRS. # see full.…

Android 性能优化入门(三)—— ANR 问题分析

需要清楚 ANR 的概念、类型、如何产生以及如何定位分析。 1、概述 1.1 ANR 的概念 ANR&#xff08;Application Not Responding&#xff09;应用程序无响应。如果你应用程序在主线程被阻塞太长时间&#xff0c;就会出现 ANR&#xff0c;通常出现 ANR&#xff0c;系统会弹出一…