嗯...在搜索“volatile”关键字时发现了这一点..lol 1. 即使使用缓存,寄存器访问也比内存快得多。例如,如果您有以下内容:
for(i = 0; i < 10000; i++)
{
// whatever...
}
如果变量 i 存储在寄存器中,则循环获得更好的性能。所以一些编译器可能会生成将 i 存储在寄存器中的代码。在循环结束之前,对该变量的更新可能不会发生在内存中。甚至完全有可能 i 永远不会写入内存(例如,i 以后永远不会使用)或溢出到循环体内(例如,内部有一个更重的嵌套循环需要优化,并且没有更多的寄存器)。该技术称为寄存器分配。只要语言标准允许,通常没有优化器规则。它有很多不同的算法。当它发生时很难回答。这就是janneb这么说的原因。如果一个变量没有及时更新,对于多线程代码来说可能真的很糟糕。例如,如果您有这样的代码:
bool objRead = false;
createThread(prepareObj); // objReady will be turn on in prepareObj thread.
while(!objReady) Sleep(100);
obj->doSomething();
优化器可能生成只测试 objReady 一次的代码(当控制流进入循环时),因为它在循环内部没有改变。这就是为什么我们需要确保读写真的像我们在多线程代码中设计的那样发生。
重新排序比寄存器分配更复杂。编译器和您的 CPU 都可能会更改代码的执行顺序。
void prepareObj()
{
obj = &something;
objReady = true;
}
对于prepareObj函数的观点,不管是先设置objReady还是先设置obj指针都没有关系。由于不同的原因,编译器和 CPU 可能会颠倒两条指令的顺序,例如特定 CPU 流水线的更好并行性、更好的缓存命中数据局部性。您可以阅读 janneb 建议的《计算机体系结构:定量方法》一书。如果我没记错的话,附录 A 是关于重新排序的(如果没有,请转到附录 B 或 C..lol)。