【问题标题】:delphi - class static method, static var in multi thread applicationdelphi - 类静态方法,多线程应用程序中的静态变量
【发布时间】:2013-05-18 08:17:54
【问题描述】:

我对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 会从最后一个值开始连续计数,还是从零开始计数不同值的不同线程?

【问题讨论】:

  • 使用 TSomeClass.SomeProcedure 调用您可以将其视为一个简单的过程,它可能是线程保存的,也可能不是线程保存的,取决于实现。如果 SomeClassInstance 的分配发生变化,使用 SomeClassInstance.SomeProcedure 可能会崩溃。
  • 是的,正如 bummi 所暗示的,如果在多线程场景中更新状态,您将需要使用临界区或其他一些同步原语来防止数据损坏。
  • 是的,如果该方法实现访问另一个类上的另一个数据,它不是线程安全的,我更新我的问题以明确我的观点,仅访问同一类中的类 var 的类静态方法怎么样?

标签: multithreading delphi class methods static


【解决方案1】:

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

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

如果两个不同的线程访问了这个方法,怎么样 F计数器? FCounter 将从最后一个值开始连续计数 还是不同值的不同线程从零开始?

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

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

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

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

【讨论】:

  • 我更新了我的问题以明确我的观点,是的,方法访问共享数据,如果该数据可以被该方法之外的另一个方法访问,但是只能使用该方法访问同一个类的数据呢?
  • 你的问题已经很清楚了,更新不会改变我的信息。你误解了分享。正如我所说,重要的是线程之间的共享而不是类之间的共享。并行执行的单位是线程而不是类。
【解决方案2】:

你的类不是线程安全的。

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

【讨论】:

  • TInterlocked 的解决方案首先发布在我的回答中。从另一个答案中复制解决方案然后得到公认的答案似乎是不公平的。
猜你喜欢
  • 1970-01-01
  • 2012-11-24
  • 1970-01-01
  • 1970-01-01
  • 2011-06-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多