什么是乐观锁?原理、实现方式与实战详解

在高并发系统中,如何保证数据一致性,又尽量提升系统性能,是一个绕不开的话题。乐观锁正是在这种背景下被广泛使用的一种并发控制机制。本文将从概念、原理、实现方式、应用场景和实战案例等方面,带你系统理解什么是乐观锁。


文章目录

一、什么是乐观锁?

1. 乐观锁的定义

乐观锁(Optimistic Lock),是一种对并发冲突持"乐观态度"的锁机制。

它的核心思想是:

认为并发冲突发生的概率较低,操作时不加锁,提交时再校验。

如果发现数据被修改过,就重试或失败处理。


2. 通俗理解

乐观锁可以理解为:

  • "先干活,后检查"
  • "出问题再重来"

就像写文档时:

先编辑,保存时提示冲突再处理。

不会一开始就锁住文件。


二、乐观锁的工作原理

乐观锁的一般执行流程:

  1. 读取数据
  2. 记录版本号/状态值
  3. 修改数据
  4. 提交时校验版本
  5. 校验成功则更新,否则失败重试

示意流程:

本质上:

通过校验机制,而不是阻塞机制保证一致性。


三、乐观锁的主要实现方式

1. 基于版本号(Version)实现

这是最常见的乐观锁方案。

数据库表结构示例:

sql 复制代码
ALTER TABLE product ADD version INT;

更新时校验版本:

sql 复制代码
UPDATE product
SET stock = stock - 1, version = version + 1
WHERE id = 1 AND version = 3;

特点:

  • 只有版本匹配才会更新成功
  • 否则返回 0 行受影响
  • 调用方决定是否重试

2. 基于时间戳实现

使用时间字段判断数据是否被修改。

示例:

sql 复制代码
WHERE id = 1 AND update_time = '2026-02-14 10:00:00'

本质与版本号类似,但精度依赖时间戳。


3. CAS(Compare And Swap)机制

在 Java 并发包中,大量使用 CAS 实现乐观锁。

示例:

java 复制代码
AtomicInteger count = new AtomicInteger(0);
count.compareAndSet(0, 1);

CAS 逻辑:

如果当前值等于期望值,则更新,否则失败。


四、乐观锁 vs 悲观锁

理解乐观锁,必须和悲观锁对比来看。

对比维度 乐观锁 悲观锁
并发态度 乐观 悲观
是否加锁
冲突处理 重试 阻塞
性能 稳定
适合场景 读多写少 写多冲突多

一句话总结:

冲突少用乐观锁,冲突多用悲观锁。


五、乐观锁的典型使用场景

1. 读多写少系统

例如:

  • 商品信息查询
  • 配置中心
  • 用户资料

读远大于写,冲突概率低。


2. 高并发但低冲突场景

例如:

  • 抢优惠券
  • 抽奖系统
  • 秒杀预减库存

适合乐观锁提升吞吐量。


3. 分布式系统

在微服务环境中,加锁成本高,乐观锁更常用。


六、实战案例:库存扣减

1. 不安全写法

java 复制代码
stock = stock - 1;

可能导致超卖。


2. 基于版本号的乐观锁实现

sql 复制代码
UPDATE goods
SET stock = stock - 1,
    version = version + 1
WHERE id = 1 AND version = #{version};

Java 伪代码:

java 复制代码
while (true) {
    Goods goods = query();
    boolean success = update(goods);
    if (success) break;
}

失败则重试。


七、乐观锁的优缺点分析

优点

  • 并发性能高
  • 无阻塞
  • 吞吐量大
  • 适合分布式系统

缺点

  • 实现复杂
  • 重试成本高
  • 冲突多时性能下降
  • 可能出现 ABA 问题

八、使用乐观锁的注意事项

1. 控制重试次数

避免无限重试导致 CPU 飙高。

建议设置最大重试次数。


2. 防止 ABA 问题

ABA:值变了又变回原值。

解决方案:

  • 加版本号
  • 使用带时间戳的标记

3. 结合业务降级处理

多次失败时:

  • 返回失败
  • 排队处理
  • 转人工

避免系统雪崩。


九、面试常见问题

1. 什么是乐观锁?

答:

不加锁,通过版本校验保证一致性。


2. 乐观锁适合什么场景?

答:

读多写少、冲突少场景。


3. CAS 和乐观锁关系?

答:

CAS 是乐观锁的底层实现方式之一。


参考

Java并发常见面试题总结(中)

相关推荐
Wang's Blog11 分钟前
Go-Zero 项目开发43:基于 Filebeat 收集各个服务的日志信息
开发语言·golang·go-zero·filebeat
2601_9537208216 分钟前
【计算机毕业设计】基于Spring Boot的心理健康咨询与评测系统的设计与实现
java·spring boot·后端
丈剑走天涯1 小时前
JDK 17 正式特性
java·开发语言
秋田君1 小时前
QT_QFontDialog类字体对话框
开发语言·qt
圣光SG1 小时前
Java操作题练习(七)
java·开发语言·算法
麻瓜老宋3 小时前
AI开发C语言应用按步走,表达式计算器calc的第二十三步,多行输入、进制输出、错误恢复、常量折叠、配置加载等
c语言·开发语言·atomcode
q567315233 小时前
企业级 HTTP 代理采购选型:技术评估清单 15 项
开发语言·网络·爬虫·网络协议·http·隧道ip·代理ip
@航空母舰3 小时前
SpringBoot通过Map实现天然的策略模式
java·spring boot·后端
天天进步20154 小时前
Python全栈项目--智能办公自动化系统
开发语言·python
Co_Hui4 小时前
Java 并发编程
java