我的想法是使用Absolute,但我不确定,这可能会引入其他副作用。
简短回答:不会。
然而,如果您遵循以下方法:
在读取跨线程可见位置时,在执行任何进一步操作之前将其值保存到本地;同样,将写入限制为单个分配。
我不知道编译器的保守方法是否会更改读取或写入的次数。
当涉及到非内联方法调用的情况下,Delphi编译器不会对非局部位置表达式执行常见子表达式消除(CSE),因为编译器不进行跨程序优化,这对于单线程代码也是不正确的。
因此,您可能需要使用InterlockedExchange()来执行读取和写入以强制执行此操作。此外,这将导致完整的内存屏障,因此处理器也不会重新排序读取和写入。
[volatile]
属性:
从 Delphi 10.1 Berlin 开始,桌面编译器也支持The
volatile
attribute is used to mark fields that are subject to change by different threads, so that code generation does not optimize copying the value in a register or another temporary memory location.You can use the
volatile
attribute to mark the following declarations:
- Variables (global and local)
- Parameters
- Fields of a record or a class.
You cannot use the volatile attribute to mark the following declarations:
- Type
- Procedures, Functions or Methods
- Expressions
type TMyClass = class private [volatile] FMyVariable: TMyType; end;
[volatile]
。现在,所有 Delphi 编译器都支持以下属性:所有编译器支持的属性 不安全 易失性 弱引用。我不知道有任何等效的方法,也不认为absolute指令会对您有所帮助。 absolute允许您拥有使用相同地址的两个变量,但我不认为它会防止编译器优化对该内存的引用。
我想您可以使用指针并自行管理它。这样,无论编译器对指针值的检索进行了什么优化,它都不应假定存储在地址处的值与上次读取它时相同,但这只是纯粹的猜测。
Delphi for .Net没有这个关键字,但是.Net平台有相应的工具函数。请参见Thread.VolatileRead和Thread.VolatileWrite。
使用动态分配指针吗?
var
MyVarPtr: ^integer;
begin
New(MyVarPtr);
MyVarPtr^ := 5;
...
这样可以防止编译器为整数值使用寄存器(但它可能仍然会为地址使用寄存器)。不过我不确定这与volatile相比如何。
volatile
的解释至多是不够准确的。 - David Heffernan