线程可以安全地读取由VCL事件设置的变量吗?

Rob*_*ank 5 delphi multithreading

线程读取由Delphi VCL事件设置的变量是否安全?

当用户单击VCL TCheckbox时,主线程将布尔值设置为复选框的Checked状态.

CheckboxState := CheckBox1.Checked;
Run Code Online (Sandbox Code Playgroud)

在任何时候,线程都会读取该变量

if CheckBoxState then ...
Run Code Online (Sandbox Code Playgroud)

如果线程"错过"对布尔值的更改并不重要,因为线程会检查循环中的变量,因为它会执行其他操作.所以它最终会看到状态变化......

这样安全吗?或者我需要特殊代码?围绕变量的读写(分别在线程和主线程中)是否需要充分的关键代码调用?

正如我所说的,如果线程获得"错误"值并不重要,但我一直认为如果一个线程在主线程处于写入过程中尝试读取变量时可能存在低级问题它,反之亦然.

我的问题类似于这个问题:对一个变量的跨线程读取是不重要的.

(也与我之前的问题有关:在Thread中使用EnterCriticalSection来更新VCL标签)

mgh*_*hie 6

这是安全的,原因有三:

  • 只有一个线程写入变量.

  • 变量只有一个字节,因此无法读取不一致的值.它将被视为True或被视为False.Delphi boolean值不存在对齐问题.

  • Delphi编译器不会对变量是否实际写入进行广泛检查,如果没有,则不会"优化"任何代码.将始终读取非局部变量,不需要说明volatile符.

话虽如此,如果你真的不确定这个,你可以使用一个integer值而不是布尔值,并使用该InterlockedExchange()函数写入变量.这在这方面有点过头了,但这是一个很好的技术,因为对于单机字大小的值,它可以消除锁的需要.

您还可以boolean通过适当的同步原语(如事件)替换它,并在其上设置线程块 - 这将有助于消除线程中的繁忙循环.