static修饰符本身不确保线程安全,是否线程安全取决于对静态变量的读写方式;多个线程同时读写易引发竞态条件,需通过加锁、原子类、volatile、线程安全容器或不可变模式来保障。

static 修饰符本身不确保线程安全,它只表示变量属于类、在类加载时初始化一次、被所有实例共享。是否线程安全,取决于对该静态变量的读写方式,而非 static 关键字本身。
静态变量为什么容易线程不安全
多个线程同时读写同一个静态变量(尤其是写操作),会引发竞态条件。例如:
- count++ 不是原子操作:读取 → 修改 → 写回,三步之间可能被其他线程打断;
- 两个线程同时执行 count = 5; 后又都设为 10,中间若穿插了其他赋值或计算,结果就不可预测;
- 普通 ArrayList 等非线程安全集合被声明为 public static,多线程 add/remove 会导致 ConcurrentModificationException 或数据丢失。
保证静态变量线程安全的常用方式
核心思路是:控制对共享状态的并发访问,或避免共享可变状态。
- 加锁同步:用 synchronized 代码块或方法保护写操作区域,确保同一时刻只有一个线程能修改该变量;
- 使用原子类:如 AtomicInteger、AtomicReference 替代 int、Object 类型的静态变量,利用 CAS 机制实现无锁线程安全;
- volatile 修饰(仅限特定场景):适用于“一个线程写、多个线程读”的简单状态标志(如 isShutdown),它保证可见性但不保证原子性;
-
使用线程安全容器:如将 static List
替换为 static CopyOnWriteArrayList 或 Collections.synchronizedList(...); - 初始化阶段保证安全:静态变量在类加载时完成初始化(如 static final Map = new HashMap()),且之后不再修改,天然线程安全(不可变模式)。
静态方法内局部变量是安全的
虽然问题聚焦于静态变量,但需注意:static 方法中定义的局部变量(如 int i = 0;)每个线程调用时都在自己的栈帧中创建副本,不共享,因此默认线程安全。真正风险来自方法内部对 static 字段的访问和修改。
避免常见误解
不要因为用了 static 就认为“系统自动管同步”——JVM 不会为 static 变量加锁或做内存屏障;也不要认为“只在 static 块里赋值就万事大吉”,如果 static 块中启动了新线程并异步修改该变量,依然可能出错。关键看运行期是否存在多线程并发写。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











