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

标签 multithreading delphi tlist

我已经构建了一个简单的日志记录类,并想确认它是线程安全的。基本上是Log , RegisterLoggerUnRegisterLogger将从不同的线程调用。 Log将被调用很多(来自许多不同的线程)和 RegisterLoggerUnRegisterLogger很少。

基本上我的问题可以归结为:“读取 TList<x> 线程安全吗?”,也就是说我可以有多个线程访问 TList 吗?同时。

IExecutionCounterLogger是一个带有 Log 方法的接口(interface)(与 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;

作为更多背景知识,这是 this question 的后续内容。 。基本上,我已经为 (DCOM) DataSnap 服务器的每个方法添加了一些工具,而且我还连接到每个 TDataSnapProvider OnGetData 和 OnUpdateData 事件。

最佳答案

Are reads on TList<T> thread safe? That is to say can I have multiple threads accessing a TList<T> at the same time?

这是线程安全的,不需要同步。多个线程可以安全地并发读取。这相当于(实际上是实现为)从数组中读取。仅当您的线程之一修改了列表时才需要同步。

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

关于multithreading - 在 Delphi 中,读取 TList<x> 线程安全吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21974211/

相关文章:

multithreading - ServerEndpoint 的每个方法是否由不同的线程执行?

delphi应用程序存在权限问题。为什么?

delphi - 如何从 Delphi 中的 TList<> 读取分组数据

Delphi 2010 : Confusing generic type TList scenario? 按值传递还是引用传递?

delphi - 如何对类型列表进行排序

java - Spring websocket线程模型

c# - 允许多个线程访问图像

Delphi - 什么对象(多维数组等)可以工作?

asp.net - 如何获取当前的登录用户,包括Delphi 2009中的域?

.net - 如何在.net 中并行启动多个操作?