当前位置: 首页 > news >正文

Java 并发大坑:volatile、synchronized、Lock 三者如何选择?

Java 并发大坑:volatile、synchronized、Lock 三者如何选择?

很多 Java 程序员对volatilesynchronizedLock的理解停留在“背八股”层面:

volatile 保证可见性,synchronized 重量级,Lock 更灵活。

但真正写并发代码时,选错一个,线上就是事故。本文从原理 → 适用场景 → 典型坑点 → 选择决策表,一次性讲清楚三者的正确打开方式。


一、先给结论(速查版)

场景

推荐

单纯状态标志(如停止线程)

volatile

复合操作(i++、check-then-act)

volatile/ ✅synchronized/ ✅Lock

单线程写、多线程读

volatile

临界区保护、简单互斥

synchronized(首选)

需要公平锁、可中断、超时、多条件队列

Lock(ReentrantLock)

高并发 + 低竞争

synchronized(JVM 优化好)

高并发 + 高竞争 + 复杂控制

Lock

👉一句话原则

能用volatile就别用锁;能用synchronized就别用Lock


二、volatile:最容易被误用的关键字

1️⃣ volatile 到底解决了什么?

volatile 只解决两个问题:

可见性

禁止指令重排序

不保证原子性

// 错误示例 private volatile int count = 0; public void increment() { count++; // 非原子操作! }

count++实际是三步:

  1. 读取 count

  2. count + 1

  3. 写回 count

多线程下必然出问题。


2️⃣ volatile 的正确使用姿势

✅ 场景一:状态标志(最常见 & 最正确)
class Worker implements Runnable { private volatile boolean running = true; public void stop() { running = false; } @Override public void run() { while (running) { // do work } } }

✔ 一个线程写,多个线程读

✔ 无复合操作

✔ 完美匹配 volatile


✅ 场景二:双重检查锁定(DCL)
class Singleton { private static volatile Singleton instance; public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } }

⚠️没有 volatile = 可能返回半初始化对象


3️⃣ volatile 的经典误区

❌ 误区 1:volatile可以替代锁

❌ 误区 2:volatile i++是线程安全的

❌ 误区 3:volatile一定比锁快(在竞争激烈时未必)


三、synchronized:被低估的王者

1️⃣ synchronized 做了什么?

synchronized保证:

✅ 原子性

✅ 可见性

✅ 有序性(临界区内)

本质:互斥 + 内存屏障


2️⃣ JVM 对 synchronized 的优化(非常重要)

很多人还停留在“synchronized 是重量级锁”的旧认知里。

现代 JVM(JDK 8+)已经实现了锁升级机制:

无锁 → 偏向锁 → 轻量级锁 → 重量级锁
  • 低竞争:几乎无开销

  • 高竞争:自动升级,性能可控

👉在大多数业务系统中,synchronized 性能优于 Lock


3️⃣ synchronized 的最佳实践

public class Counter { private int count = 0; public synchronized void increment() { count++; } public synchronized int getCount() { return count; } }

✔ 简单

✔ 安全

✔ 不易出错


4️⃣ synchronized 的局限性

❌ 无法响应中断

❌ 无法尝试获取锁(tryLock)

❌ 无法实现公平锁

❌ 条件队列只有一个(wait/notify)

当你需要这些能力时,才考虑Lock


四、Lock:功能最强,但最危险

1️⃣ Lock 的核心优势

ReentrantLock lock = new ReentrantLock(); lock.lock(); try { // 临界区 } finally { lock.unlock(); }

✅ 可中断(lockInterruptibly

✅ 超时获取锁(tryLock(timeout)

✅ 公平锁

✅ 多条件变量(Condition


2️⃣ Lock 的典型使用场景

✅ 场景一:可中断锁
lock.lockInterruptibly(); try { // 处理任务 } finally { lock.unlock(); }

用于防止死锁、响应线程中断


✅ 场景二:多条件队列
Condition notFull = lock.newCondition(); Condition notEmpty = lock.newCondition();

这是synchronized + wait/notify做不到的。


3️⃣ Lock 的大坑(90% 的人踩过)

忘记 unlock

lock.lock(); doSomething(); // 抛异常 → 锁永远不释放

✅ 必须放在finally


重复加锁导致死锁

lock.lock(); lock.lock(); // 忘了解锁一次

性能反而更差

在低竞争场景下,Lock的性能通常不如synchronized


五、三者对比总结(面试 & 实战必看)

特性

volatile

synchronized

Lock

原子性

可见性

有序性

部分

可重入

可中断

公平锁

多条件队列

复杂度

⭐⭐

⭐⭐⭐⭐

推荐程度

慎用

⭐⭐⭐⭐⭐

⭐⭐⭐


六、选择决策流程图(建议收藏)

是否只是状态标志? ├─ 是 → volatile └─ 否 是否需要复杂锁控制(中断/超时/公平/多条件)? ├─ 是 → Lock └─ 否 → synchronized

七、真实线上事故案例(警示)

💥 案例:volatile + i++ 导致库存超卖

private volatile int stock = 100; public void reduceStock() { stock--; }

结果:

✈️ 库存扣成负数

💸 资损事故

原因:volatile 不保证原子性

✅ 正确做法:

synchronized (this) { stock--; }

AtomicInteger stock = new AtomicInteger(100); stock.decrementAndGet();

八、终极建议

并发编程的第一原则是:不要自己发明并发控制。

  • 能用不可变对象就不用 volatile

  • 能用synchronized就不用Lock

  • 能用并发容器就不用手写锁

  • 能用AtomicXXX就不用synchronized


九、一句话总结

volatile 管“看见”,synchronized 管“互斥”,Lock 管“精细控制”。

能不用锁就不用锁,能用简单锁就不用复杂锁。

http://www.cnnetsun.cn/news/3778955.html

相关文章:

  • 多团队共用 Claude API,Key 管理该怎么规范
  • 8月AIOps研究计划与技术展望:基于7月实践洞察的下阶段五大重点攻关方向与预期产出
  • 微软 CEO 承诺加大 Windows 投资,多项修复能否拯救拖后腿的操作系统?
  • 图解DES、3DES与AES:从原理到实战的对称加密算法指南
  • VRRP协议深度解析:从原理到实战的高可用网络网关冗余方案
  • docker-image 工具展示更详细镜像层内容
  • 深入解析PCIe协议:从基础架构到实战调优
  • Blender 3MF格式支持:从3D设计到3D打印的无缝桥梁
  • 卫星通信系统安全威胁与防御技术解析
  • Unity Canvas渲染模式详解:粒子特效与UI融合的实战指南
  • 5分钟永久备份你的QQ空间青春回忆:GetQzonehistory完整指南
  • 大疆嵌入式面试核心考点解析:从硬件到RTOS的实战指南
  • Python极简详细入门指南,新手必读!
  • 放射组学在脑转移患者生存预测中的关键技术与应用挑战
  • DownKyi:B站视频下载终极指南与免费开源方案
  • CM6800芯片ATX电源维修:从原理到实战的开关电源故障排查指南
  • 嘉准长距离传感器:FCWY激光最远200米,F3L接近开关感应距离翻倍
  • 次贷危机深度解析:从金融工程到系统性风险的传导机制
  • OpenClaw:结构化Prompt工程与AI应用开发革新
  • 日常防止抑郁的6件小事,普通人轻松可做
  • MATLAB新手入门:从界面解析到核心指令实战
  • 3分钟搞定BetterNCM安装:网易云音乐插件管理终极指南
  • 嵌入式系统轻量化设计:从2kg重量控制到工程实践全解析
  • 文献综述不会写?用文飞AI从选题、文献匹配到大纲预览跑一遍
  • 【IEEE出版、往届刊后1个月EI检索】第七届信号处理、模式识别与计算机科学国际学术会议(SPCS 2026)
  • OpenClaw macOS版2026,兼容Ventura/Sonoma安装
  • 音游难度评级系统解析:从MSV15到AD(MAX-24)的进阶指南
  • RK3588遇上25 TOPS算力卡!LH707嵌入式主机解锁边缘AI新应用
  • 深入解析NOR Flash:从浮栅晶体管原理到嵌入式系统实战应用
  • 网络工程师职业转型:六大方向与实施路径