Multithreading 线程能否安全地读取VCL事件设置的变量?
线程读取Delphi VCL事件设置的变量是否安全 当用户单击VCL复选框时,主线程将布尔值设置为复选框的选中状态Multithreading 线程能否安全地读取VCL事件设置的变量?,multithreading,delphi,Multithreading,Delphi,线程读取Delphi VCL事件设置的变量是否安全 当用户单击VCL复选框时,主线程将布尔值设置为复选框的选中状态 CheckboxState := CheckBox1.Checked; 在任何时候,线程都会读取该变量 if CheckBoxState then ... 如果线程“遗漏”了对布尔值的更改,这无关紧要,因为线程在循环中检查变量时会执行其他操作。所以它最终会看到状态的改变 这安全吗?还是我需要特殊代码?围绕变量的读写(分别在线程和主线程中)是否有必要和足够的关键代码调用 正如我所
CheckboxState := CheckBox1.Checked;
在任何时候,线程都会读取该变量
if CheckBoxState then ...
如果线程“遗漏”了对布尔值的更改,这无关紧要,因为线程在循环中检查变量时会执行其他操作。所以它最终会看到状态的改变
这安全吗?还是我需要特殊代码?围绕变量的读写(分别在线程和主线程中)是否有必要和足够的关键代码调用
正如我所说,线程是否得到“错误”值并不重要,但我一直认为,如果一个线程试图读取变量,而主线程处于写入的中间,反之亦然,则可能存在低级问题。 我的问题与此类似:
(也与我前面的问题相关:)对于你给出的例子,它是安全的。从技术上讲,主要问题是在变量大小超过机器字的情况下,因此可能会导致高位字和长字不同步。但对于较小的值,这不是问题
如果您认为这是一个潜在的问题,例如使用指针,那么要使用的是一个TCriticalSection来控制对该项的读写。这对于所有实际情况都足够快,并确保您100%安全。这是安全的,原因有三:
- 只有一个线程写入变量
- 变量只有一个字节,因此无法读取不一致的值。它将被读取为
或True
。DelphiFalse
值不存在对齐问题boolean
- Delphi编译器不会对变量是否实际写入进行大量检查,如果没有,也不会“优化”任何代码。将始终读取非局部变量,不需要
说明符volatile
整数
值而不是布尔值,并使用函数写入变量。这在这里有些过分,但这是一个值得了解的好技术,因为对于单机器字大小的值,它可能不需要锁
您还可以使用适当的同步原语(如事件)替换布尔值,并在其上设置线程块-这将帮助您消除线程中的繁忙循环。在您的情况下(选中属性),读取操作是原子的,因此是安全的。这与TThread.Terminated属性相同;正确对齐的字节、字和双字的简单读写操作是原子的。您可以查看以了解更多信息:
第8章-多处理器管理
8.1.1保证的原子操作
Intel486处理器(以及此后更新的处理器)保证:
基本内存操作将始终以原子方式执行:
- 读或写一个字节
- 读或写在16位边界上对齐的字
- 读取或写入在32位边界上对齐的双字
奔腾处理器(以及此后的较新处理器)保证:
附加内存操作将始终以原子方式执行:
- 读取或写入64位边界上对齐的四字
- 对32位数据总线中未缓存内存位置的16位访问
请注意,VCL事件并没有什么特别之处。您的问题同样适用于从任意两个线程中的任何函数访问变量。