多线程编程学习十三(原子性、可见性与有序性)
原子性
原子(atom)指化学反应不可再分的基本微粒,原子在化学反应中不可分割。原子操作指的是不可分割的整体,多线程的原子性指的是没有其他线程能够中断或检查正在原子操作中的变量。
从内存模型来看,直接保证的原子性变量操作包括 read、load、assign、use、store 和 write,我们大致可以认为基本数据类型的访问读写是具备原子性的。
从应用场景来看,JVM 保证原子性操作的主要有以下方式:
- synchronized 关键字。锁操作,基于 monitorenter 和 monitorexit 字节码指令,保证同步块只有单一线程执行。
- AQS 锁机制。比如 ReentrantLock、ReentrantReadWriteLock 等,保证同步块只有单一线程执行。
- CAS 实现。比如 java.util.concurrent.atomic 包中的诸多实现。
- volatile 关键字。修饰变量,轻量锁机制,仅能保证对单个变量的操作具有原子性,复合操作不具备原子性。
可见性
可见性是指当一个线程修改了共享变量的值,其他线程能够立即得知这个修改。
从应用场景来看,JVM 保证可见性主要有以下方式:
-
volatile 关键字,它是如何保证可见性的呢?
- 当对 volatile 变量写的时候,会将当前处理器缓存行的数据写回到系统内存。
- 当对 volatile 变量读的时候,会将当前处理器缓存行的数据置为无效,因此要从系统内存中读取变量值。
-
synchronized 等锁机制。同步块的可见性是由“对一个变量执行 unlock 操作之前,必须先把此变量同步回主内存中(执行 store、write 操作)”这条规则获得的。
-
final 关键字。被 final 修饰的字段在构造器中一旦初始化完成,并且构造器没有把“this”的引用传递出去,那在其他线程中就能看到 final 关键字,并且该修饰能保证该对象一定是线程安全的。
private static final int i;
private final int j;
static {
i = 0;
}
{
// 也可以选择在构造函数中初始化
j = 0;
}
有序性
有序性是指如果在本线程内观察,所有的操作都是有序的;如果在一个线程中观察另一个线程,所有的操作都是无序的。前半句是指“线程内表现为串行的语义(as is serial)”,后半句是指“指令重排序”现象和“工作内存与主内存同步延迟”现象。
从应用场景来看,JVM 保证有序性主要有以下方式:
- volatile 关键字,它本身就包含了禁止指令重排序的语义。
- synchronized 等锁机制,同步块的有序性是由“一个变量在同一个时刻只允许一条线程对其进行 lock 操作”这条规则获得的。
分类:
Java多线程
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南