1.问题描述:
我在读《深入理解java虚拟机》的时候看到volatile是通过lock add $0x0,(%esp)这个字节码指令来刷新cpu缓存的,作者表示“这样所有之前的操作都已经执行完了,所以指令重排序不能越过内存屏障”,但是我觉得只是刷新的话并不能达到内存屏障的效果。
2.尝试的方案:
阅读过linux指令屏障相关文档,但是没有说明怎么实现内存屏障这种效果的
1.问题描述:
我在读《深入理解java虚拟机》的时候看到volatile是通过lock add $0x0,(%esp)这个字节码指令来刷新cpu缓存的,作者表示“这样所有之前的操作都已经执行完了,所以指令重排序不能越过内存屏障”,但是我觉得只是刷新的话并不能达到内存屏障的效果。
2.尝试的方案:
阅读过linux指令屏障相关文档,但是没有说明怎么实现内存屏障这种效果的
3 回答2.6k 阅读✓ 已解决
3 回答4.1k 阅读✓ 已解决
8 回答3.6k 阅读
4 回答2.7k 阅读✓ 已解决
2 回答2.6k 阅读✓ 已解决
3 回答2.5k 阅读✓ 已解决
3 回答1.7k 阅读✓ 已解决
内存屏障细说来有写屏障、读屏障、读写屏障,而且内存屏障的实现依赖于编译器和机器两部分:
一、编译器。编译器在编译过程中可能会对指令重排序,这样程序员通过显式地标注告知编译器避免编译器最终生成的代码行为违背预期,对于 Java 而言,不光生成的 bytecode 需要保存 volatile 的语义,连运行时的 JIT 代码的行为也要遵守相应的约束;
二、机器相关。在多核机器上内存的“可见性”是个很重要的特性,Java 的
volatile
关键字同时包含了直接访问内存的语义和内存屏障的语义。由于现代处理器大多是乱序执行的,尤其 Intel 的 x86 架构,如果我没记错的话它不仅乱序执行而且还在保证(单线程)结果的情况下乱序输出,所以读、写屏障都有专门的指令实现。Linux 作为操作系统也只是调用 CPU 所实现的内存屏障指令而已,归根结底这个不是操作系统或者编译器去实现,而是硬件实现了然后供软件调用。另外我推荐这篇文章,讲得详细的多。