volatile不能保证原子性,因其仅保障可见性和有序性,不阻止复合操作(如i++)被多线程交错执行;i++包含读、改、写三步,即使每步可见,仍可能因并发读取相同旧值导致结果丢失。

Java中不能通过“继承Thread类 + volatile”实现轻量锁。这是对并发机制的常见误解。
volatile不能保证原子性
volatile关键字仅保证变量的可见性和禁止指令重排序,但不提供原子性保障。例如对volatile int count的count++操作,实际包含读取、加1、写回三步,在多线程下仍会丢失更新。
- 即使继承Thread类并用volatile标记共享状态,多个线程同时修改该状态仍会产生竞态条件
- volatile适合用作状态标志(如running = true/false),而非计数器、累加器等需复合操作的场景
轻量锁是JVM内置的同步优化机制
轻量锁(Lightweight Locking)是HotSpot虚拟机在对象监视器(monitor)层面实现的锁优化策略,发生在synchronized块或方法上,与用户代码是否继承Thread、是否使用volatile无关。
- 它依赖对象头中的Mark Word进行锁状态切换(无锁→轻量锁→重量锁)
- 开发者无法手动“实现”轻量锁,只能通过合理使用synchronized让JVM自动启用该优化
- volatile变量不参与JVM锁升级流程,也不影响对象的锁状态
正确实现线程安全的常见方式
若目标是避免重量级锁开销,应选择JVM原生支持且语义明确的方案:
- 优先使用synchronized:现代JVM对其做了大量优化(偏向锁、轻量锁、自旋等),简单可靠
- 需要更高性能时,考虑java.util.concurrent.atomic包下的原子类(如AtomicInteger),它们基于CAS和volatile配合实现无锁编程
- 共享资源保护必须依赖同步机制(synchronized、ReentrantLock、原子类等),不能仅靠volatile + Thread子类
继承Thread类本身与锁无关
继承Thread只是定义线程执行逻辑的一种方式,和同步控制完全正交。是否继承Thread、Runnable或使用ExecutorService,都不改变并发安全的本质要求。
- Thread子类中声明volatile字段,仅对该字段的读写提供可见性,不构成锁
- 真正的互斥访问,仍需synchronized、Lock或原子操作来协调对共享数据的修改
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











