2

我对 delphi XE2 比较陌生,如果我喜欢这段代码,我想知道一些事情

TSomeClass=class
strict private
class var
   FCounter:integer;
public
   class procedure SomeProcedure();static
end;

implementation
class procedure SomeProcedure()
begin
  inc(FCounter);
end;

initialization
begin
   FCounter:=0;
end;

finalization
begin
  FCounter:=0;
end;

据我了解, SomeProcedure() 将在内存和单个实例上静态,

我的问题

  1. 如果 TSomeClass 被多个线程访问,TSomeClass 线程安全与否?或者它会使线程之间重叠?
  2. 如果是,我是否需要每个线程的关键部分?或这种方法的另一种方法......
  3. 如果两个不同的线程访问了这个方法,那么 FCounter 呢?FCounter 会从最后一个值开始计数,还是从零开始计数不同值的不同线程?
4

2 回答 2

7

不同的方法调用之间没有同步。如果方法(无论它们是什么类型的方法)访问共享数据,则可能需要同步。

它们的方法是类方法还是实例方法,静态或动态等,这没有任何区别。重要的是是否有从多个线程访问的共享对象。

如果两个不同的线程访问这个方法,那么 FCounter 呢?FCounter 会从最后一个值开始计数,还是从零开始计数不同值的不同线程?

在您的代码中,FCounter是一个类变量。该变量有一个实例,在所有线程之间共享。类变量只是一个全局变量,仅此而已。

您的代码会修改该共享变量。正如所写的那样,代码存在数据竞争。您可以通过同步来解决它。例如通过使用InterlockedIncrement而不是inc.

class procedure SomeProcedure;
begin  
  InterlockedIncrement(FCounter); 
end;

对于更复杂的对象,您将使用关键部分进行序列化。

于 2013-05-23T06:03:59.720 回答
5

您的课程不是线程安全的。

使计数器线程安全的最简单方法是使用 TInterlocked.Increment(FCounter) 而不是 Inc(FCounter)。所有 TInterlocked 方法都作为原子操作执行,同样适用于 Windows API 函数 InterlockedIncrement() 也可以在这里使用。

于 2013-05-23T07:07:03.913 回答