悲观锁与乐观锁

一、悲观锁( Pessimistic Lock

定义与核心思想

悲观锁基于"数据并发必然冲突"的假设,在访问共享资源前强制加锁,确保独占访问。其核心是"先加锁,后操作"的保守策略。

实现方式

1. Java层面

  • synchronized关键字(重量级锁实现)

  • ReentrantLock等显式锁

2. 数据库层面

  • SELECT FOR UPDATE(行级/表级锁)

  • 共享锁(S锁)、排他锁(X锁)

特点与优劣势

优势

  1. 安全性极高,严格保证数据一致性

  2. 适合临界区执行时间长的场景

劣势

1.锁开销大(用户态/内核态切换)

2.可能引起线程阻塞、优先级反转

3.死锁风险

二、乐观锁(Optimistic Lock)

定义与核心思想

乐观锁基于"数据冲突概率低"的假设,采用"先操作,后验证"的开放策略,通过版本控制实现无锁化并发。

实现方式

1. 版本号机制

数据表增加version字段,更新时校验版本[4][15][18]

2. CAS (Compare And Swap

  • 原子操作包含三个参数:内存值V、预期值A、新值B

  • 仅在V==A时更新为B,否则重试

  • Java实现:AtomicInteger等原子类

特点与优劣势

优势

  1. 无锁设计提升吞吐量

  2. 避免线程上下文切换

  3. 适合读多写少场景

劣势

  1. ABA问题(需版本号辅助解决)

  2. 高竞争场景导致频繁重试

  3. 需业务层处理冲突

三、关键差异对比

维度 悲观锁 乐观锁
并发假设 必定冲突 大概率无冲突
锁机制 显式加锁 无锁(版本控制)
冲突处理 预防冲突 检测并解决冲突
适用场景 写操作多、临界区耗时长 读操作多、临界区执行快
实现复杂度 简单(JVM/DB原生支持) 需业务层处理冲突逻辑
典型应用 银行转账、库存扣减 点赞计数、配置更新
性能表现 高安全但吞吐量低 高吞吐但存在重试开销

四、架构选型建议

  1. 优先考虑乐观锁

    • 当系统读占比超过70%

    • 业务能容忍短暂数据不一致(如缓存更新)

    • 需支持高并发(如电商秒杀库存校验)

  2. 必须使用悲观锁

    • 强事务一致性要求(如金融交易)

    • 临界区包含复杂计算(避免重复执行)

    • 无法处理重试的场景(如实时竞价系统)

  3. 混合使用策略

    • 例如JUC中的StampedLock,先尝试乐观读,冲突时升级为悲观锁

五、典型案例

  1. 悲观锁
java 复制代码
// 使用ReentrantLock转账
   public void transfer(Account from, Account to, int amount) {
       lock.lock();
       try {
           from.withdraw(amount);
           to.deposit(amount);
       } finally {
           lock.unlock();
       }
   }
  1. 乐观锁
java 复制代码
// 使用AtomicReference实现计数器
   AtomicInteger counter = new AtomicInteger(0);
   public void safeIncrement() {
       int oldValue;
       do {
           oldValue = counter.get();
       } while (!counter.compareAndSet(oldValue, oldValue + 1));
   }

在分布式系统中,可结合Redis的WATCH/MULTI命令实现乐观锁,或通过数据库的版本号字段实现多版本并发控制(MVCC)。实际架构设计中,需结合QPS、数据一致性级别、重试成本等维度综合考量。

相关推荐
缺点内向3 小时前
Java:创建、读取或更新 Excel 文档
java·excel
带刺的坐椅4 小时前
Solon v3.4.7, v3.5.6, v3.6.1 发布(国产优秀应用开发框架)
java·spring·solon
四谎真好看5 小时前
Java 黑马程序员学习笔记(进阶篇18)
java·笔记·学习·学习笔记
桦说编程5 小时前
深入解析CompletableFuture源码实现(2)———双源输入
java·后端·源码
java_t_t5 小时前
ZIP工具类
java·zip
舒一笑6 小时前
大模型时代的程序员成长悖论:如何在AI辅助下不失去竞争力
后端·程序员·掘金技术征文
lang201509286 小时前
Spring Boot优雅关闭全解析
java·spring boot·后端
小羊在睡觉6 小时前
golang定时器
开发语言·后端·golang
pengzhuofan6 小时前
第10章 Maven
java·maven
用户21411832636026 小时前
手把手教你在魔搭跑通 DeepSeek-OCR!光学压缩 + MoE 解码,97% 精度还省 10-20 倍 token
后端