volatile是如何禁止指令进行重排序的

本文涉及的产品
Serverless 应用引擎 SAE,800核*时 1600GiB*时
可观测监控 Prometheus 版,每月50GB免费额度
应用实时监控服务ARMS - 应用监控,每月50GB免费额度
简介: volatile是如何禁止指令进行重排序的

Further Reading : 内存屏障类型介绍(StoreStore,StoreLoad,LoadLoad,LoadStore)
Further Reading : 什么是指令重排

重排序分为编译器重排序和处理器重排序。 为了实现volatile内存语义,JMM会分别限制这两种类型的重排序类型。

● volatile禁止的重排序
1、当第二个操作是volatile写时,不管第一个操作是什么,都不能重排序。这个规则确保volatile写之前的操作不会被编译器重排序到volatile写之后。
2、当第一个操作是volatile读时,不管第二个操作是什么,都不能重排序。这个规则确保volatile读之后的操作不会被编译器重排序到volatile读之前。
3、当第一个操作是volatile写,第二个操作是volatile读时,不能重排序。

●JMM针对编译器制定的volatile重排序规则表
在这里插入图片描述

● volatile如何禁止重排序的?
编译器在生成字节码时,会在指令序列中插入内存屏障来禁止特定类型的处理器重排序。
第1步:在每个volatile写操作的前面插入一个StoreStore屏障,后面插入一个StoreLoad屏障。
在这里插入图片描述

●StoreStore屏障 禁止上面普通写与下面volatile写重排序,上面普通读与下面volatile写如何禁止重排序?
虽然StoreStore屏障主要作用于防止store-store重排序,但在volatile写操作中实际会使用更复杂的内存屏障组合,以确保volatile写之前的普通读不会被重排到volatile写之后。

第2步:在每个volatile写操作的后面插入一个StoreLoad屏障
StoreLoad屏障 禁止 volatile写和volatile读重排序

因为编译器常常无法准确判断在一个volatile写的后面是否需要插入一个StoreLoad屏障(比如,一个volatile写之后方法立即return)。为了保证能正确实现volatile的内存语义,JMM在采取了保守策略:在每个volatile写的后面,或者在每个volatile读的前面插入一个StoreLoad屏障。从整体执行效率的角度考虑,JMM最终选择了在每个volatile写的后面插入一个StoreLoad屏障。因为volatile写-读内存语义的常见使用模式是:一个写线程写volatile变量,多个读线程读同一个volatile变量。当读线程的数量大大超过写线程时,选择在volatile写之后插入StoreLoad屏障将带来可观的执行效率的提升。从这里可以看到JMM在实现上的一个特点:首先确保正确性,然后再去追求执行效率。

第3步:在每个volatile读操作的后面插入一个LoadLoad屏障,一个LoadStore屏障。

在这里插入图片描述

LoadLoad屏障+LoadStore屏障 禁止 普通读,普通写 和volatile读重排序

相关文章
|
5月前
|
存储 缓存 安全
JMM学习笔记(二) 规则和volatile
JMM学习笔记(二) 规则和volatile
|
缓存
指令重排序的探讨
指令重排序是现代处理器为了提高指令级并行性和性能而进行的一种优化技术。在高并发场景下,指令重排序可能会引发一些问题,本文将详细介绍指令重排序的概念、原因、影响以及如何解决这些问题。
171 0
|
5月前
|
缓存 Java 编译器
关于volatile与指令重排序的探讨
关于volatile与指令重排序的探讨
69 1
|
5月前
|
缓存 Java 编译器
JMM内存模型 volatile关键字解析
JMM内存模型 volatile关键字解析
38 0
|
5月前
|
Java 编译器 开发者
为什么代码会重排序
在并发编程中,重排序是一项为了提高性能而进行的优化策略。理解重排序的原理和可能引发的问题对于编写高效且正确的多线程代码至关重要。Java提供了一些机制,如内存屏障,来帮助开发者在多线程环境下保持程序的正确性和可靠性。
48 0
|
5月前
|
Java
6.什么是内存屏障?具有什么作用?
6.什么是内存屏障?具有什么作用?
74 0
6.什么是内存屏障?具有什么作用?
|
存储 缓存 Java
volatile的扩展分析(2)——happens-before 与 内存屏障
volatile的扩展分析(2)——happens-before 与 内存屏障
238 0
volatile的扩展分析(2)——happens-before 与 内存屏障
|
缓存 Java 编译器
避免重排序之使用 Volatile 关键字
volatile 关键字本身就包含了禁止指令重排序的语义,仅保证赋值过程的原子性,保障变量的可见性,但不具备排它性
235 0
|
编译器
什么是指令重排序?
什么是指令重排序?
什么是指令重排序?
volatile的指令禁重排(六)
volatile的指令禁重排
130 0
volatile的指令禁重排(六)