Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 线程能否安全地读取VCL事件设置的变量?_Multithreading_Delphi - Fatal编程技术网

Multithreading 线程能否安全地读取VCL事件设置的变量?

Multithreading 线程能否安全地读取VCL事件设置的变量?,multithreading,delphi,Multithreading,Delphi,线程读取Delphi VCL事件设置的变量是否安全 当用户单击VCL复选框时,主线程将布尔值设置为复选框的选中状态 CheckboxState := CheckBox1.Checked; 在任何时候,线程都会读取该变量 if CheckBoxState then ... 如果线程“遗漏”了对布尔值的更改,这无关紧要,因为线程在循环中检查变量时会执行其他操作。所以它最终会看到状态的改变 这安全吗?还是我需要特殊代码?围绕变量的读写(分别在线程和主线程中)是否有必要和足够的关键代码调用 正如我所

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

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

CheckboxState := CheckBox1.Checked;
在任何时候,线程都会读取该变量

if CheckBoxState then ...
如果线程“遗漏”了对布尔值的更改,这无关紧要,因为线程在循环中检查变量时会执行其他操作。所以它最终会看到状态的改变

这安全吗?还是我需要特殊代码?围绕变量的读写(分别在线程和主线程中)是否有必要和足够的关键代码调用

正如我所说,线程是否得到“错误”值并不重要,但我一直认为,如果一个线程试图读取变量,而主线程处于写入的中间,反之亦然,则可能存在低级问题。 我的问题与此类似:


(也与我前面的问题相关:)

对于你给出的例子,它是安全的。从技术上讲,主要问题是在变量大小超过机器字的情况下,因此可能会导致高位字和长字不同步。但对于较小的值,这不是问题


如果您认为这是一个潜在的问题,例如使用指针,那么要使用的是一个TCriticalSection来控制对该项的读写。这对于所有实际情况都足够快,并确保您100%安全。

这是安全的,原因有三:

  • 只有一个线程写入变量

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

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

话虽如此,如果您确实对此不确定,您可以使用
整数
值而不是布尔值,并使用函数写入变量。这在这里有些过分,但这是一个值得了解的好技术,因为对于单机器字大小的值,它可能不需要锁

您还可以使用适当的同步原语(如事件)替换
布尔值,并在其上设置线程块-这将帮助您消除线程中的繁忙循环。

在您的情况下(选中属性),读取操作是原子的,因此是安全的。这与TThread.Terminated属性相同;正确对齐的字节、字和双字的简单读写操作是原子的。您可以查看以了解更多信息:

第8章-多处理器管理

8.1.1保证的原子操作

Intel486处理器(以及此后更新的处理器)保证: 基本内存操作将始终以原子方式执行:

  • 读或写一个字节
  • 读或写在16位边界上对齐的字
  • 读取或写入在32位边界上对齐的双字
奔腾处理器(以及此后的较新处理器)保证: 附加内存操作将始终以原子方式执行:

  • 读取或写入64位边界上对齐的四字
  • 对32位数据总线中未缓存内存位置的16位访问

请注意,VCL事件并没有什么特别之处。您的问题同样适用于从任意两个线程中的任何函数访问变量。