JMM——volatile与内存屏障
2016-03-30 13:08
781 查看
为了实现volatile内存语义,JMM会分别限制编译器重排序和处理器重排序
1.当第一个操作为普通的读或写时,如果第二个操作为volatile写,则编译器不能重排序这两个操作(1,3)
2.当第一个操作是volatile读时,不管第二个操作是什么,都不能重排序。这个规则确保volatile读之后的操作不会被编译器重排序到volatile读之前(第二行)
3.当第一个操作是volatile写,第二个操作是volatile读时,不能重排序(3,2)
4.当第二个操作是volatile写时,不管第一个操作是什么,都不能重排序(第三列)
为了实现volatile的内存语义,编译器在生成字节码时,会在指令序列中插入内存屏障来禁止特定类型的处理器重排序。
JMM基于保守策略的JMM内存屏障插入策略:
1.在每个volatile写操作的前面插入一个StoreStore屏障
2.在每个volatile写操作的后面插入一个SotreLoad屏障
3.在每个volatile读操作的后面插入一个LoadLoad屏障
4.在每个volatile读操作的后面插入一个LoadStore屏障
上图的StoreStore屏障可以保证在volatile写之前,其前面的所有普通写操作已经对任意处理器可见了
因为StoreStore屏障将保障上面所有的普通写在volatile写之前刷新到主内存
x86处理器仅仅会对写-读操作做重排序
因此会省略掉读-读、读-写和写-写操作做重排序的内存屏障
在x86中,JMM仅需在volatile后面插入一个StoreLoad屏障即可正确实现volatile写-读的内存语义
这意味着在x86处理器中,volatile写的开销比volatile读的大,因为StoreLoad屏障开销比较大
1.当第一个操作为普通的读或写时,如果第二个操作为volatile写,则编译器不能重排序这两个操作(1,3)
2.当第一个操作是volatile读时,不管第二个操作是什么,都不能重排序。这个规则确保volatile读之后的操作不会被编译器重排序到volatile读之前(第二行)
3.当第一个操作是volatile写,第二个操作是volatile读时,不能重排序(3,2)
4.当第二个操作是volatile写时,不管第一个操作是什么,都不能重排序(第三列)
为了实现volatile的内存语义,编译器在生成字节码时,会在指令序列中插入内存屏障来禁止特定类型的处理器重排序。
JMM基于保守策略的JMM内存屏障插入策略:
1.在每个volatile写操作的前面插入一个StoreStore屏障
2.在每个volatile写操作的后面插入一个SotreLoad屏障
3.在每个volatile读操作的后面插入一个LoadLoad屏障
4.在每个volatile读操作的后面插入一个LoadStore屏障
上图的StoreStore屏障可以保证在volatile写之前,其前面的所有普通写操作已经对任意处理器可见了
因为StoreStore屏障将保障上面所有的普通写在volatile写之前刷新到主内存
x86处理器仅仅会对写-读操作做重排序
因此会省略掉读-读、读-写和写-写操作做重排序的内存屏障
在x86中,JMM仅需在volatile后面插入一个StoreLoad屏障即可正确实现volatile写-读的内存语义
这意味着在x86处理器中,volatile写的开销比volatile读的大,因为StoreLoad屏障开销比较大
相关文章推荐
- C中的volatile使用方法
- 探讨C语言中关键字volatile的含义
- 学习Java多线程之volatile域
- C语言中auto,register,static,const,volatile的区别详细解析
- C语言中const,volatile,restrict的用法总结
- C语言 volatile与const同时使用应注意的问题
- 深入解析Java中volatile关键字的作用
- 解析java中volatile关键字
- 深度解析Java中volatile的内存语义实现以及运用场景
- JAVA中JVM的重排序详细介绍
- 详解Java线程编程中的volatile关键字的作用
- 深入探讨Java多线程中的volatile变量
- 深入讲解C语言编程中volatile修饰符的作用
- 大话JMM
- Java理论与实践:正确使用volatile 变量
- 一个由JIT优化引发的问题
- Const Volatile 关键词解析
- const与volatile的使用方法
- volatile的作用
- volatile, 用更低的代价替代同步