在Delphi中读取TList <x>线程安全吗?

Ali*_*ter 6 delphi multithreading tlist

我已经构建了一个简单的日志记录类,并希望确认它是线程安全的.基本上Log,RegisterLogger并将UnRegisterLogger从不同的线程调用. Log将被称为很多(来自许多不同的线程),RegisterLogger并且UnRegisterLogger很少.

基本上我的问题可归结为:" TList<x>线程读取是否安全?",也就是说我可以让多个线程同时访问a TList.

IExecutionCounterLogger是一个具有Log方法的接口(具有相同的签名TExecutionCounterServer.Log)

Type
  TExecutionCounterServer = class
  private
    Loggers : TList<IExecutionCounterLogger>;
    Synchronizer : TMultiReadExclusiveWriteSynchronizer;
  public
    procedure RegisterLogger(Logger : IExecutionCounterLogger);
    procedure UnRegisterLogger(Logger : IExecutionCounterLogger);
    procedure Log(const ClassName, MethodName : string; ExecutionTime_ms : integer);

    constructor Create;
    destructor Destroy; override;
  end;

constructor TExecutionCounterServer.Create;
begin
  Loggers := TList<IExecutionCounterLogger>.Create;
  Synchronizer := TMultiReadExclusiveWriteSynchronizer.Create;
end;

destructor TExecutionCounterServer.Destroy;
begin
  Loggers.Free;
  Synchronizer.Free;
  inherited;
end;

procedure TExecutionCounterServer.Log(const ClassName, MethodName: string; ExecutionTime_ms: integer);
var
  Logger: IExecutionCounterLogger;
begin
  Synchronizer.BeginRead;
  try
    for Logger in Loggers do
      Logger.Log(ClassName, MethodName, ExecutionTime_ms);
  finally
    Synchronizer.EndRead;
  end;
end;

procedure TExecutionCounterServer.RegisterLogger(Logger: IExecutionCounterLogger);
begin
  Synchronizer.BeginWrite;
  try
    Loggers.Add(Logger);
  finally
    Synchronizer.EndWrite;
  end;
end;

procedure TExecutionCounterServer.UnRegisterLogger(Logger: IExecutionCounterLogger);
var
  i : integer;
begin
  Synchronizer.BeginWrite;
  try
    i := Loggers.IndexOf(Logger);
    if i = -1 then
      raise Exception.Create('Logger not present');
    Loggers.Delete(i);  
  finally
    Synchronizer.EndWrite;
  end;
end;
Run Code Online (Sandbox Code Playgroud)

作为更多背景,这是从这个问题的后续.基本上我已经为(DCOM)DataSnap服务器的每个方法添加了一些工具,我也已经连接到每个TDataSnapProvider OnGetData和OnUpdateData事件.

Dav*_*nan 8

TList<T>线程读取是否安全?也就是说我可以让多个线程同时访问一个TList<T>

这是线程安全的,不需要同步.多个线程可以安全地同时读取.这相当于(并且实际上实现为)从数组中读取.只有当您的某个线程修改了需要同步的列表时.

您的代码比此方案稍微复杂一些.您似乎需要满足修改列表的线程.但你已经这样做了,TMultiReadExclusiveWriteSynchronizer这是一个非常好的解决方案.它允许多个读取线程同时操作,但任何写入线程都相对于所有其他线程进行序列化.