Delphi-TDictionary线程安全吗? [英] Delphi - Is TDictionary thread safe

查看:341
本文介绍了Delphi-TDictionary线程安全吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的想法是使用TDictionary来管理IdTCPServer上的客户端连接.这是一个简单的示例代码(未经测试),用于理解目的:

My idea is to use TDictionary to manage client connections on IdTCPServer. Here is a simple example code (not tested) for understanding purposes:

var
  Dic: TDictionary<string, TIdContext>;

procedure TfrmMain.FormCreate(Sender: TObject);
begin
  Dic := TDictionary<string, TIdContext>.Create;
end;

procedure TfrmMain.FormDestroy(Sender: TObject);
begin
  Dic.Free;
end;

procedure TfrmMain.TCPServerConnect(AContext: TIdContext);
var
  Hostname: string;
begin
  Hostname := UpperCase(GStack.HostByAddress(AContext.Binding.PeerIP));
  if not Dic.ContainsKey(Hostname) then Dic.Add(Hostname, AContext);
end;

procedure TfrmMain.TCPServerDisconnect(AContext: TIdContext);
var
  Hostname: string;
begin
  Hostname := UpperCase(GStack.HostByAddress(AContext.Binding.PeerIP));
  if Dic.ContainsKey(Hostname) then
  begin
    Dic[Hostname].Free;
    Dic.Remove(Hostname);
  end;
end;

此代码线程安全吗?

推荐答案

简而言之:.

如果您检查 TDictionary 的来源,您应该很快意识到,实现本身没有关于线程安全的规定.即使是这样,通过离散调用 Dic 实例,您可能需要解决以下竞争条件:

If you inspect the source of TDictionary you should quickly realise that there is no provision for thread-safety in the implementation itself. Even if it were, by having discrete calls to a Dic instance you have potential race conditions to contend with:

  if Dic.ContainsKey(Hostname) then
  begin

    // In theory the Hostname key may be removed by another thread before you 
    //  get a chance to do this : ...

    Dic[Hostname].Free;
    Dic.Remove(Hostname);
  end;

您需要自己使用 Dic 线程安全,幸运的是,在这种示例中,使用对象本身的监视器可以轻松实现此目的:

You need to make your own use of Dic thread safe, and fortunately in this sort of example this is easily achieved using a monitor on the object itself:

MonitorEnter(Dic);
try
  if not Dic.ContainsKey(Hostname) then 
    Dic.Add(Hostname, AContext);

finally
  MonitorExit(Dic);
end;


// ....


MonitorEnter(Dic);
try
  if Dic.ContainsKey(Hostname) then
  begin
    Dic[Hostname].Free;
    Dic.Remove(Hostname);
  end;

finally
  MonitorExit(Dic);
end;

如果您不熟悉Delphi中的监视器,可以简单地说,您可以将监视器视为每个 TObject 后代(在较早版本的Delphi中,不支持这些监视器,您可以通过显式的关键部分来实现相同的目的.

If you are not familiar with monitors in Delp in simple terms you can think of a monitor as a ready-to-use critical section supported by every TObject descendant (in older versions of Delphi which did not support these monitors you could have achieved the same thing with an explicit critical section).

这篇关于Delphi-TDictionary线程安全吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆