Wrayの知识库 Wrayの知识库
首页
  • Java 基础
  • Java 集合
  • Java 并发
  • Java IO
  • JVM
  • Spring Framework
  • Spring Boot
  • Spring Cloud
  • Spring Security
  • MySQL
  • Redis
  • 计算机基础
  • 操作系统原理
  • Linux
  • MacOS
  • Windows
  • 系统工程与研究专题
  • AI 基础
  • 大模型基础
  • Prompt 工程
  • RAG 检索增强生成
  • Agent 智能体
  • AI 应用开发
  • AI 工程化
  • AI 安全与治理
  • AI 面试与设计题
  • 纸质书
  • 电子书
  • 学习课程
疑难杂症
GitHub (opens new window)
首页
  • Java 基础
  • Java 集合
  • Java 并发
  • Java IO
  • JVM
  • Spring Framework
  • Spring Boot
  • Spring Cloud
  • Spring Security
  • MySQL
  • Redis
  • 计算机基础
  • 操作系统原理
  • Linux
  • MacOS
  • Windows
  • 系统工程与研究专题
  • AI 基础
  • 大模型基础
  • Prompt 工程
  • RAG 检索增强生成
  • Agent 智能体
  • AI 应用开发
  • AI 工程化
  • AI 安全与治理
  • AI 面试与设计题
  • 纸质书
  • 电子书
  • 学习课程
疑难杂症
GitHub (opens new window)
  • Java章节编写规范
  • Java基础

  • Java集合

  • Java并发

    • Java并发概述
    • 线程与进程
    • Thread类与线程生命周期
    • 线程创建与任务模型
    • 线程安全
      • 1. 什么是线程安全
      • 2. 线程安全三要素
      • 3. 共享状态
      • 4. 竞态条件
      • 5. 线程安全策略
        • 5.1 不共享
        • 5.2 不可变
        • 5.3 加锁
        • 5.4 原子类
        • 5.5 并发容器
      • 6. 安全发布
      • 7. 常见线程不安全类
      • 8. 判断一个类是否线程安全
      • 9. 线程安全与性能
      • Tips 快问快答
    • synchronized关键字
    • volatile关键字
    • Java内存模型(JMM)
    • 线程间通信
    • 线程池
    • 并发工具类
    • 原子操作类Atomic
    • 并发锁
    • 并发容器
    • ConcurrentHashMap
    • BlockingQueue
    • CopyOnWriteArrayList
    • ThreadLocal
    • Fork/Join框架
    • ScheduledThreadPoolExecutor
    • CompletableFuture
    • 虚拟线程
    • 死锁活锁与线程问题排查
    • 并发编程最佳实践
  • Java IO

  • JVM

  • Java
  • Java并发
Wray
2026-06-24
目录

线程安全

线程安全指多个线程同时访问同一段代码或同一个对象时,无论线程如何交替执行,程序都能得到正确结果,并保持对象状态一致。

线程安全不是“加了锁就安全”,而是要明确共享状态、并发访问路径和同步策略。

# 1. 什么是线程安全

一个类在多线程环境下仍能保持正确性,可以称为线程安全。

public class Counter {
    private int count;

    public void increment() {
        count++;
    }
}

count++ 不是线程安全的。

线程 A 读取 count = 0
线程 B 读取 count = 0
线程 A 写回 1
线程 B 写回 1

执行两次 increment,结果却是 1

# 2. 线程安全三要素

问题 含义 解决方式
原子性 操作不能被打断 锁、原子类
可见性 一个线程修改,其他线程能看到 volatile、锁、final、安全发布
有序性 禁止破坏语义的重排序 volatile、锁、happens-before

很多并发 bug 是三者叠加的结果。

# 3. 共享状态

线程安全问题的根源是共享可变状态。

共享 + 可变 + 多线程访问
        │
        ▼
    需要并发控制

没有共享,就没有竞争:

public int add(int a, int b) {
    int result = a + b;
    return result;
}

局部变量在线程栈中,每个线程独有,通常天然线程安全。局部变量引用的对象如果逃逸到其他线程,则另当别论。

# 4. 竞态条件

竞态条件指程序结果依赖线程执行时序。

if (stock > 0) {
    stock--;
}

可能出现:

stock = 1

线程 A 判断 stock > 0 为 true
线程 B 判断 stock > 0 为 true
线程 A stock-- -> 0
线程 B stock-- -> -1

判断和扣减必须作为一个整体保护。

# 5. 线程安全策略

# 5.1 不共享

使用局部变量、方法参数、线程封闭。

public void handle() {
    List<String> values = new ArrayList<>();
}

# 5.2 不可变

不可变对象天然线程安全。

public final class Money {
    private final BigDecimal amount;

    public Money(BigDecimal amount) {
        this.amount = amount;
    }
}

# 5.3 加锁

public synchronized void increment() {
    count++;
}

锁同时提供互斥和可见性。

# 5.4 原子类

AtomicInteger count = new AtomicInteger();
count.incrementAndGet();

适合单变量原子更新。

# 5.5 并发容器

ConcurrentHashMap<String, User> map = new ConcurrentHashMap<>();

不要用普通集合自己拼装复杂同步,除非边界非常清晰。

# 6. 安全发布

对象构造完成后,其他线程必须以安全方式看到它。

安全发布方式:

  • 通过 final 字段。
  • 通过 volatile 引用。
  • 通过锁保护。
  • 放入线程安全容器。
  • 在线程启动前完成初始化。

错误示例:

private User user;

public void init() {
    user = new User();
}

如果没有同步,其他线程可能看到未完全初始化的对象状态。

# 7. 常见线程不安全类

类 问题
ArrayList 并发 add 可能丢数据或越界
HashMap 并发 put 状态不安全
SimpleDateFormat 内部状态可变
StringBuilder 可变且非同步
普通 int 计数器 ++ 非原子

替代:

场景 替代
并发 List 读多写少 CopyOnWriteArrayList
并发 Map ConcurrentHashMap
日期格式化 DateTimeFormatter
计数 AtomicLong、LongAdder
字符串局部拼接 局部 StringBuilder

# 8. 判断一个类是否线程安全

检查:

  • 是否有共享可变字段。
  • 字段是否会在多个线程访问。
  • 每个访问路径是否有统一同步策略。
  • 复合操作是否被整体保护。
  • 对象是否安全发布。
  • 是否把内部可变集合直接暴露给外部。

# 9. 线程安全与性能

线程安全通常有成本:

  • 加锁会有竞争和阻塞。
  • 原子类在高竞争下 CAS 重试。
  • CopyOnWrite 写入复制数组。
  • 不可变对象可能增加对象创建。

不要凭感觉优化,要通过压测和监控判断瓶颈。

# Tips 快问快答

Q:线程安全的根源问题是什么? A:共享可变状态被多个线程同时访问。

Q:局部变量一定线程安全吗? A:局部变量本身通常安全,但它引用的对象如果逃逸到其他线程就不一定。

Q:count++ 为什么不安全? A:它包含读、加、写多个步骤,不是原子操作。

Q:锁解决哪些问题? A:同时解决互斥、可见性和一定的有序性问题。

Q:不可变对象为什么线程安全? A:对象状态创建后不再变化,多线程读取不会产生竞争。

Q:什么是安全发布? A:让其他线程看到对象引用时,也能看到对象构造完成后的正确状态。

Q:线程安全类一定性能差吗? A:不一定,要看实现和竞争程度,但同步通常有成本。

Q:如何优先避免线程安全问题? A:减少共享状态,优先使用不可变对象和线程封闭。

上次更新: 2026/06/24, 17:22:59
线程创建与任务模型
synchronized关键字

← 线程创建与任务模型 synchronized关键字→

Copyright © 2023-2026 Wray | 鄂ICP备2024050235号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式