内存屏障,也称内存栅栏,内存栅障,屏障指令等, 是一类同步屏障指令,是CPU或编译器在对内存随机访问的操作中的一个同步点,使得此点之前的所有读写操作都执行后才可以开始执行此点之后的操作。---百度百科
个人理解:就类似于我们喝茶的时候需要先把水煮开(限定条件),然后再切茶,而这一整套流程都是限定特定环节的先后顺序(内存屏障),保障切出来的茶可以更香。
由于现在计算机存在多级缓存且多核场景,为了保证读取到的数据一致性以及并行运行时所计算出来的结果一致,在硬件层面实现一些指令,从而来保证指定执行的指令的先后顺序。比如上图:双核cpu,每个核心都拥有独立的一二级缓存,而缓存与缓存之间需要保证数据的一致性所以这里才需要加添屏障来确保数据的一致性。三级缓存为各CPU共享,最后都是主内存,所以这些存在交互的CPU都需要通过屏障手段来保证数据的唯一性。
内存屏障解决了什么问题?内存屏障指令仅仅直接控制CPU与其缓存之间,CPU与其准备将数据写入主存或者写入等待读取、预测指令执行的缓冲中的写缓冲之间的相互操作。
内存屏障主要解决重排序导致的内存乱序访问问题,由于现代硬件的发展,cpu存在多级缓存,所以为了保障一些执程的执行顺序不会因为重排优化导致乱序的情况,所以硬件产商引入了读、写屏障,主要就是保证了执行的顺序能够根据需要的特定场景进行标识防止重排序。cpu屏障有哪些?
●Store:将处理器缓存的数据刷新到内存中。●Load:将内存存储的数据拷贝到处理器的缓存中。
屏障类型 | 指令示例 | 说明 |
---|---|---|
LoadLoad Barriers | Load1;LoadLoad;Load2 | 该屏障限制Load1优先于Load2及后续的指令装载。 |
StoreStore Barriers | Store1;StoreStore;Store2 | 该屏障确保store立即刷新数据到内存(并且对其他处理器可见)优先于Store2及后续的指令操作, |
LoadStore Barriers | Load1;LoadStore;Store2 | 该屏障确保Load1加载数据优先于Store2及后续的指令存储刷新到内存中。 |
StoreLoad Barriers | Store1;StoreLoad;Load2 | 该屏障确保Store1立刻刷新数据到内存的操作优先于Load及后续的指令装载的操作。 |
最后 内存屏障是基于硬件提供的屏障指令来实现的,可以这样说,不同的CPU或者说厂商所实现的内存屏障不一定完全相同,但肯定存在保障屏障的指令,在操作不同的操作系统也是会根据这些不同的厂商提供的指令进行实现屏障,而在java中你volatile会根据操作系统或硬件提供的屏障来实现可见性以及禁止重排序问题。当然其他语言也有大量的应用,只是基于硬件层面,需要了解硬件、操作系统、指令实现,该问题的确比较深入,要了解硬件层面知识,又要了解部分操作系统以及语言的虚拟机中引擎的实现。当然基于本文可以从较全的来了解内存屏障的实现原理和使用场景。
参考文献https://baike.baidu.com/item/%E5%86%85%E5%AD%98%E5%B1%8F%E9%9A%9C/13014423
https://ifeve.com/memory-barriers-or-fences/
https://www.jianshu.com/p/08a0a8c984ab
https://zhuanlan.zhihu.com/p/270269628
https://www.jianshu.com/p/64240319ed60
https://www.cnblogs.com/chenny7/p/13589241.html
https://www.jianshu.com/p/2ab5e3d7e510
https://tech.meituan.com/2016/11/18/disruptor.html