我见过类似的问题(前here和here),但从未见过明确的答案。假设我们有以下代码:
..
I:= 1;
I:= 2;
..
Delphi编译器保证优化器永远不会消除第一个赋值,并通过将数据写入I
变量的内存地址来实现,而不仅仅是某个处理器寄存器,如果I
是全局或基于堆(例如对象的字段)变量?
答案 0 :(得分:3)
启用优化后,上面的代码(至少在某些情况下)会被优化以删除第一个分配。所以这可能不是一个很好的例子!
通过这个最小的例子可以看出这一点:
program OptimiseMe;
{$APPTYPE CONSOLE}
{$O+}//switch optimisations on
var
I: Integer;
begin
I := 1;
I := 2;
if I>0 then
;
end.
但是,我从未遇到过编译器将基于全局或基于堆的变量优化到寄存器中的问题。似乎总是把它写回内存。但我相信你不会在文件中找到任何保证任何内容的东西。
但是,这与MSVC易失性不同,因为高速缓存阻塞并且没有使用内存屏障或栅栏。即使Delphi编译器发出将值写入内存的指令,它也会首先进入运行代码的处理器的缓存中。在高速缓存已经同步之前,在其他处理器上执行的代码将无法看到该写入。
如果要在线程之间共享这样的变量,最简单的方法可能是使用InterlockedXXX函数来强制执行必要的障碍,并确保所有线程都具有一致的变量视图。
注意:当你谈到volatile时,你需要小心,因为有很多不同的定义。 C和C ++标准中定义的含义是一个。 MSVC编译器具有符合标准但更强的定义。它在Java和C#中又有所不同。这里有很多复杂性,InterlockedXXX函数是隐藏这种复杂性的好方法。