2025.6.6
多线程执行 int a = 1; int b = 2; int c = a + b; 的问题分析
你提供的代码:
int a = 1; // 指令1
int b = 2; // 指令2
int c = a + b; // 指令3
在 单线程 环境下,这段代码的执行顺序不会影响最终结果(c 始终是 3)。
但在 多线程 环境下,如果多个线程同时执行这段代码,可能会遇到以下问题:
1. 多线程执行时的潜在问题
(1) 指令重排(Instruction Reordering)
- 编译器或 CPU 可能会优化指令顺序,例如:
- 先执行
int b = 2;(指令2),再执行int a = 1;(指令1)。 - 如果线程 A 执行
a = 1但还没执行b = 2,线程 B 读取a和b时可能得到a=1, b=0(默认值),导致c计算错误。
- 先执行
(2) 内存可见性问题(Visibility)
- 由于 CPU 缓存(Cache)的存在,一个线程修改的变量可能不会立即被其他线程看到。
- 例如:
- 线程 A 执行
a = 1,但该值可能只写入 CPU 缓存,线程 B 仍然读到a=0(初始值)。
- 线程 A 执行
(3) 竞态条件(Race Condition)
- 如果多个线程同时修改
a或b,最终c的值可能不符合预期。 - 例如:
- 线程 A 执行
a = 1,线程 B 同时执行a = 5,最终a的值可能是1或5,导致c计算错误。
- 线程 A 执行
2. 如何让这段代码线程安全?
(1) 使用 synchronized 加锁
public class Example {
private int a, b, c;
public synchronized void calculate() {
a = 1; // 指令1
b = 2; // 指令2
c = a + b; // 指令3
}
}
- 优点:简单直接,保证原子性和可见性。
- 缺点:性能较差,多个线程不能并行执行。
(2) 使用 volatile 禁止指令重排
public class Example {
private volatile int a, b, c;
public void calculate() {
a = 1; // 指令1
b = 2; // 指令2
c = a + b; // 指令3
}
}
- 优点:比
synchronized更轻量,防止指令重排。 - 缺点:不能保证原子性(如果多个线程同时调用
calculate(),仍然可能出错)。
(3) 使用 AtomicInteger(无锁优化)
import java.util.concurrent.atomic.AtomicInteger;
public class Example {
private final AtomicInteger a = new AtomicInteger();
private final AtomicInteger b = new AtomicInteger();
private final AtomicInteger c = new AtomicInteger();
public void calculate() {
a.set(1); // 指令1
b.set(2); // 指令2
c.set(a.get() + b.get()); // 指令3
}
}
- 优点:无锁,性能较好。
- 缺点:仍然不能保证
a和b的修改是原子的(如果多个线程同时调用calculate(),c可能计算错误)。
(4) 使用 ThreadLocal(线程隔离)
public class Example {
private static final ThreadLocal<Integer> a = ThreadLocal.withInitial(() -> 0);
private static final ThreadLocal<Integer> b = ThreadLocal.withInitial(() -> 0);
private static final ThreadLocal<Integer> c = ThreadLocal.withInitial(() -> 0);
public void calculate() {
a.set(1); // 指令1
b.set(2); // 指令2
c.set(a.get() + b.get()); // 指令3
}
}
- 优点:每个线程有自己的变量副本,完全避免竞争。
- 缺点:适用于线程隔离的场景,不适用于共享变量。
3. 结论
| 方案 | 适用场景 | 线程安全保证 | 性能 |
|---|---|---|---|
synchronized |
需要强一致性 | ✅ 原子性 + 可见性 | 较差 |
volatile |
仅需可见性 | ❌ 原子性,✅ 可见性 | 较好 |
AtomicInteger |
无锁优化 | ❌ 原子性(复合操作),✅ 可见性 | 较好 |
ThreadLocal |
线程隔离 | ✅ 无竞争 | 最佳 |
推荐方案
- 如果多个线程需要共享计算 → 用
synchronized或ReentrantLock保证原子性。 - 如果只是防止指令重排 → 用
volatile。 - 如果每个线程独立计算 → 用
ThreadLocal。
最终线程安全版本(推荐 synchronized)
public class Example {
private int a, b, c;
public synchronized void calculate() {
a = 1;
b = 2;
c = a + b;
}
public synchronized int getC() {
return c;
}
}
这样,无论多少线程调用 calculate(),c 的值始终是 3。

浙公网安备 33010602011771号