在C#中,以下代码(来自this页面)可用于以线程安全的方式懒惰地实例化单例类:
class Foo {
private volatile Helper helper = null;
public Helper getHelper() {
if (helper == null) {
lock(this) {
if (helper == null)
helper = new Helper();
}
}
return helper;
}
}
什么是等效的线程安全的Delphi代码?
文章还提到了Java中双重检查锁定的两个问题:
因此,虽然上述文章中的C#代码和Java版本看起来几乎相同,但只有C#版本按预期工作。如果在Delphi版本的Double-Checked Locking中也存在这两个问题,那么会引出另外一个问题?
答案 0 :(得分:7)
使用System.TMonitor以线程安全的方式锁定对象实例。
function TFoo.GetHelper(): THelper;
begin
if not Assigned(FHelper) then
begin
System.MonitorEnter(Self);
try
if not Assigned(FHelper) then
FHelper := THelper.Create();
finally
System.MonitorExit(Self);
end;
end;
Result := FHelper;
end;
如需进一步参考,请查看Lock my object..., please!的Allen Bauer。事实上,代表。我从中收集应该去艾伦。
答案 1 :(得分:2)
当然,总是值得记住Double-Checked Locking is Broken。这个问题不适用于x86内存模型,但总是值得考虑未来。我确信在某些时候会有Delphi版本在一个平台上运行,该平台的内存模型会受到这个问题的影响。
Embarcadero已开始使用此模式的无锁版本与互锁比较/交换。例如:
class function TEncoding.GetUnicode: TEncoding;
var
LEncoding: TEncoding;
begin
if FUnicodeEncoding = nil then
begin
LEncoding := TUnicodeEncoding.Create;
if InterlockedCompareExchangePointer(Pointer(FUnicodeEncoding), LEncoding, nil) <> nil then
LEncoding.Free;
end;
Result := FUnicodeEncoding;
end;
我意识到这不是问题的答案,但它并不适合评论!