Delphi是否有任何与C的volatile变量等价的东西?

时间:2008-10-24 00:16:48

标签: c multithreading delphi volatile memory-model

在C和C ++中,变量可以标记为volatile,这意味着编译器不会对其进行优化,因为它可以在声明对象外部进行修改。在Delphi编程中是否有相同的东西?如果不是关键字,也许可以解决?

我的想法是使用绝对,但我不确定,这可能会引入其他副作用。

5 个答案:

答案 0 :(得分:15)

简答:不。

但是,如果您遵循这种方法,我不知道编译器的保守方法会改变读取或写入次数的任何情况:

在读取跨线程可见位置时,在进行任何进一步操作之前将其值保存到本地;同样,限制写入单个分配。

当在表达式之间调用非内联方法时,Delphi编译器不对非本地位置表达式执行公共子表达式消除(CSE),因为编译器不进行过程间优化,因此它不正确甚至对于单线程代码也是如此。

因此,您可能希望使用InterlockedExchange()来执行读取和写入操作;此外,这将导致完整的内存屏障,因此处理器也不会重新排序读取和写入。

答案 1 :(得分:8)

根据The Delphi Language for Mobile Development白皮书,Delphi的移动编译器自首次推出以来一直支持[volatile]属性:

  

volatile属性用于标记可能由不同线程更改的字段,因此代码生成不会优化复制寄存器或其他临时内存位置中的值。

     

您可以使用volatile属性标记以下声明:

     
      
  • 变量(全局和本地)
  •   
  • 参数
  •   
  • 记录或班级的字段。
  •   
     

您不能使用volatile属性标记以下声明:

     
      
  • 输入
  •   
  • 程序,功能或方法
  •   
  • 表达
  •   
     

type
  TMyClass = class
  private
    [volatile] FMyVariable: TMyType;
  end;

从Delphi 10.1 Berlin开始,桌面编译器现在也支持[volatile]

Attributes Supported by All Compilers

  

现在,所有Delphi编译器都支持以下属性:

     

答案 2 :(得分:1)

我不知道任何等价物,也不认为绝对指令会对您有所帮助。 绝对允许你有两个使用相同地址的变量,但我认为它不会阻止编译器优化对该内存的引用。

我想你可以使用指针并自己管理它。无论编译器如何优化指针值的优化,它都不应该假设存储在地址中的值与上次读取时的值相同,但这是纯粹的推测。

答案 3 :(得分:1)

Delphi for .Net也没有关键字,但.Net平台有for util函数。请参阅Thread.VolatileReadThread.VolatileWrite

答案 4 :(得分:0)

使用动态分配的指针?

var
  MyVarPtr: ^integer;
begin
  New(MyVarPtr);
  MyVarPtr^ := 5;
...

这应该使编译器不使用寄存器来获取整数值(但它可能仍然使用一个作为地址)。不过,我不确定这与挥发性有何不同。