一、线程安全的核心概念
线程安全是Java并发编程的核心问题,指当多个线程同时访问一个对象时,不需要额外的同步措施,调用该对象的行为都能获得正确结果。其本质是保证共享数据的一致性,避免因线程交替执行导致的竞态条件(Race Condition)或数据不一致。
1. 线程安全的分类(按安全程度)
根据《Java并发编程实战》及Java API文档,线程安全可分为以下几类:
-
不可变(Immutable):对象状态永不改变,天生线程安全。例如
String、Integer、BigInteger等(通过final关键字修饰状态,或构造后无法修改)。 -
绝对线程安全:无论运行环境如何,调用者无需额外同步即可安全使用。这类对象极少,如
Vector的get()、remove()方法虽同步,但连续调用(如遍历+删除)仍需额外同步。 -
相对线程安全:单次操作线程安全,但连续调用可能需要额外同步。Java中大多数声称线程安全的类(如
Vector、Collections.synchronizedList())均属此类。 -
线程兼容:对象本身不安全,但可通过调用端同步(如
synchronized)保证安全。例如ArrayList、HashMap。 -
线程对立:无论调用端如何同步,均无法在多线程环境下安全使用(极少,如
System.setOut())。
2. 线程安全问题的根源
线程安全问题源于共享数据的非同步访问,具体表现为:
-
原子性破坏:非原子操作(如
i++,包含读-改-写三步)被线程切换打断,导致更新丢失。 -
可见性缺失:线程A修改的共享变量未及时刷新到主内存,线程B读取到旧值。
-
有序性错乱:编译器/处理器的指令重排序改变执行顺序,导致逻辑错误(如单例模式的“空指针”问题)。
二、Java线程安全的实现方式
Java提供了多种机制保证线程安全,按使用复杂度和灵活性排序如下:
1. 不可变对象(最安全)
原理:对象状态永不改变,无需同步。
实现方式:
-
基本数据类型用
final修饰(如final int a = 10); -
引用数据类型用
final修饰且不暴露修改方法(如String的substring()返回新对象); -
使用
Collections.unmodifiableXXX()包装集合(如unmodifiableList(),修改操作抛UnsupportedOperationException)。
示例:

最低0.47元/天 解锁文章
956

被折叠的 条评论
为什么被折叠?



