synchronized 不直接保证原子性,而是通过互斥访问和内存屏障间接实现代码块级别的逻辑原子性;其本质是同步机制,提供互斥与 happens-before 关系,适用于多步骤复杂逻辑,而 atomicinteger 等则基于 cas 提供指令级原子操作。

synchronized 本身不直接“保证原子性”,而是通过互斥访问 + 内存可见性保障,间接让被它保护的代码块在多线程环境下表现出原子性行为。
原子性不是 synchronized 的直接能力
Java 中真正的原子性由底层指令(如 CAS、lock 前缀指令)或 JVM 对某些操作(如读写 volatile long/double、引用赋值)的保证提供。synchronized 是一种同步机制,它的核心作用是:
- 确保同一时刻最多只有一个线程能进入被它修饰的代码块或方法(互斥);
- 建立“进入锁”和“释放锁”两个内存屏障,强制刷新主内存与工作内存之间的变量状态(happens-before 关系)。
当多个操作被包裹在同一个 synchronized 块中,且没有其他线程能同时执行该段逻辑时,这段逻辑对外就表现为“不可分割”的整体——即我们常说的“原子性效果”。
典型原子性场景:复合操作必须加锁
像 i++ 这类操作实际包含读取、修改、写入三步,在多线程下天然非原子。仅靠 synchronized 保护才能使其安全:
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- 错误写法:
int i = 0; public void increment() { i++; }→ 非原子,可能丢失更新; - 正确写法:
public synchronized void increment() { i++; }或public void increment() { synchronized(this) { i++; } }→ 整个 i++ 被串行化执行。
注意:synchronized 不改变单条指令的原子性
它不能让原本非原子的指令变成原子(比如 64 位 long 在 32 位 JVM 上的非对齐读写),也不能替代 volatile 对单次读/写的可见性优化。它的“原子性”始终是以代码块为单位的逻辑原子性,而非 CPU 指令级原子性。
替代方案对比:synchronized vs AtomicInteger
对于简单计数器等场景,AtomicInteger 提供了基于 CAS 的无锁原子操作,性能通常更好:
-
synchronized:适合较复杂、多步骤、需保证整体一致性的业务逻辑; -
AtomicInteger.incrementAndGet():适合单个变量的简单原子更新,底层依赖 CPU 原子指令。
二者目标一致(避免竞态),但实现路径不同:一个是阻塞式互斥,一个是乐观并发控制。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










