内存屏障介绍
- 内存屏障(memory barrier)是一种保证内存顺序访问的方法,用来解决下面这些内存乱序访问的问题。出现内存乱序访问一般有3个方面的因素
- 编译器编译代码时候可能会重新排列汇编指令,使编译出来的程序在处理器上更快,但是有时候优化的结果可能不符合程序设计者的意图。
- 现代处理器采用标量体系结构和乱序执行 技术,能够在一个时钟周期内并发执行多条指令,处理器按照指令顺序取出,分析出没有依赖关系的指令然后发给多个处理器执行,最后按照顺序提交执行结果。用一句话总结就是
顺序取出,乱序执行,顺序提交结果执行
。在有些情况下,处理器无法识别指令之间的关系,这时就会导致指乱序执行导致执行结果不符合预期 - 多CPU处理器系统中,有些程序设计者会使用存储缓冲区,引入处理器之间的内存访问乱系的问题,一个处理器修改了数据,可能不会立即同步到自己的缓存或者其他处理器缓存,到时其他处理器不能立即看到最新的数据。
- 内核目前支持三种内存屏障,
编译器屏障
、处理器内存屏障
、内存映射IO写屏障
。这里着重介绍编译器屏障
编译器屏障
- 为提高程序代码的执行效率,编译器对代码进行优化,对于不存在依赖关系的汇编指令,重新排列他们的顺序,但是编译器优化的结果不符合预期,开发者需要去控制或者阻止这种编译器优化。
barrier()
是编译器提供的屏障的函数,这个函数会阻止编译器把屏障一侧的指令移动到另一侧,既不把屏障前面的指令移动到屏障后面,也不能把屏障后面的指令移动到屏障前面,编译器屏障也叫做编译器优化屏障。内核定义了宏READ_ONCE()、WRITE_ONCE()和ACCESS_ONCE()可以看做barrier()
弱化形式,只阻止编译器对于单个变量优化,C语言提供了关键字volatile
可以防止编译器优化单个变量。