TCriticalSection是否允许对变量进行多线程访问?

时间:2011-07-15 04:19:19

标签: multithreading delphi

我想同步线程以访问公共变量。 想象一下,我有N个线程,每个线程都可以访问TSyncThreds类型变量的全局实例。

我可以调用方法IncCount,DecCount吗?或者我会遇到并发线程访问对象的同一个实例的问题?

我只是同步访问FCcounter变量......

type
  TSyncThreads = class

  public
    FCounterGuard: TCriticalSection;
    FCounter: integer;
    FSimpleEvent: TSimpleEvent;

    constructor Create();
    procedure Wait();
    procedure IncCounter();
    procedure DecCounter();
  end;


var
  SyncThread: TSyncThreads;

implementation
uses
  Math, Windows, Dialogs;



{ TSyncThreads }

procedure TSyncThreads.DecCounter;
begin
  FCounterGuard.Acquire;
  Dec(FCounter);
  if FCounter = 0 then
    FSimpleEvent.SetEvent;
  FCounterGuard.Release;
end;

procedure TSyncThreads.IncCounter;
begin
  FCounterGuard.Acquire;
  Inc(FCounter);
  FCounterGuard.Release;
end;

constructor TSyncThreads.Create();
begin
  FCounter := 0;
  FSimpleEvent := TSimpleEvent.Create;
  FCounterGuard := TCriticalSection.Create;
  FSimpleEvent.ResetEvent;
end;

procedure TSyncThreads.Wait;
var
  ret: TWaitResult;
begin
  ret := FSimpleEvent.WaitFor(INFINITE);
end;

1 个答案:

答案 0 :(得分:8)

是的,如果手头的任务有点过分,你的代码就可以了。您担心多个线程访问同一个对象,但这正是TCriticalSection和TEvent等同步对象的设计目标。想象一下,如果无法同时访问这些类,这些类将是多么毫无意义。

您并不需要一个关键部分来保护您的柜台访问权限。您可以使用InterlockedIncrement和InterlockedDecrement进行更轻量级的访问。它们返回变量的先前值,因此如果InterlockedDecrement返回1,那么您知道是时候设置事件了。

如果计数器上有一个上限,那么你甚至可以避免所有这些代码并改为使用信号量。或者您可以为每个线程设置自己的事件,然后使用WaitForMultipleObjects等待所有事件;所有线程都设置了事件后它将返回,因此您不必同步访问任何共享变量。