gpt4 book ai didi

multithreading - Delphi - TDictionary 线程安全吗

转载 作者:可可西里 更新时间:2023-11-01 02:32:23 26 4
gpt4 key购买 nike

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

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 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 的使用是线程安全的,幸运的是,在此类示例中,使用对象本身的监视器可以轻松实现这一点:

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 中,不支持这些监视器,您可以通过显式关键部分实现相同的目的)。

关于multithreading - Delphi - TDictionary 线程安全吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27517063/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com