枚举类型 - 线程安全

时间:2018-01-16 11:45:50

标签: multithreading delphi

我和一位同事争论有关枚举类型的线程安全问题。具有以下简单枚举类型:

type Suit = (Club, Diamond, Heart, Spade);

并在类中声明为变量,如下面的虚拟代码:

type 
TTest = class
private 
  FSuit: Suit;
  function SetSuit(aValue: Suit);
public
  property GimmeSuit: Suit read FSuit;

.....

function SetSuit(aValue: Suit);
begin
  FSuit:= aValue;
end;

我说这段代码是线程安全的,因为设置FSuit变量的值是一个原子操作。我错了吗?我没有在网上找到关于这个案子的任何内容。

1 个答案:

答案 0 :(得分:11)

您需要明确使用的术语 threadsafe atomic ,然后才能正确解决。

  • Threadsafe 是一个模糊的术语,必须根据其应用的特定上下文进行限定。 Eric Lippert的经典文章What is this thing you call "thread safe"?
  • 详细介绍了这一点
  • 原子操作是不可分割的操作。系统的其他部分似乎同时发生。

在您展示的代码中,我假设多个线程都在读取和写入FSuit

完成所有这些操作后,读取和写入FSuit是原子的,只要它是单个字节或对齐。

单字节内存访问始终是原子的。如果枚举类型大于单个字节,则必须将内存读/写对齐为原子。未对齐的内存访问可以撕裂。也就是说,读取线程可能只看到写入的一部分,因为该变量跨越了高速缓存行。写入线程必须将变量的一部分写入一个高速缓存行,然后将其余部分写入相邻的高速缓存行,并且读取线程可以通过两阶段写入过程读取整个变量。

现在,使用默认设置,此枚举类型将是单个字节,并且类布局将对齐。因此,即使对较大的枚举类型进行读/写也是原子的。

至于您的程序是否是线程安全的,无法从此处的信息中确定。你需要澄清意图是什么。例如,假设两个线程写入FSuit,第三个线程从中读取。如果程序的正确性不依赖于那些内存访问的顺序,那么它就是线程安全的。如果它的正确性取决于排序,则它不是线程安全的并且需要同步。