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

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


文章目录

一、什么是乐观锁?

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并发常见面试题总结(中)

相关推荐
YDS8298 小时前
黑马点评 —— 分布式锁详解加源码剖析
java·spring boot·redis·分布式
ZTLJQ8 小时前
数据的基石:Python中关系型数据库完全解析
开发语言·数据库·python
夏霞8 小时前
c# signlar 客户端传递参数给服务端配置方法
开发语言·c#
迷藏4948 小时前
**发散创新:基于 Rust的开源权限管理系统设计与实战**在现代软件架构中,**权限控制**早已不
java·开发语言·rust·开源
升鲜宝供应链及收银系统源代码服务8 小时前
《IntelliJ + Claude Code + Gemini + ChatGPT 实战配置手册升鲜宝》
java·前端·数据库·chatgpt·供应链系统·生鲜配送
daidaidaiyu8 小时前
Nacos实例一则及其源码环境搭建
java·spring
2301_818419018 小时前
C++中的解释器模式变体
开发语言·c++·算法
小江的记录本9 小时前
【Redis】Redis全方位知识体系(附《Redis常用命令速查表(完整版)》)
java·数据库·redis·后端·python·spring·缓存
摇滚侠9 小时前
Java 项目《谷粒商城-1》架构师级Java 项目实战,对标阿里 P6-P7,全网最强,实操版本
java·开发语言
biter down9 小时前
C++11 统一列表初始化+std::initializer_list
开发语言·c++