【发布时间】:2019-01-09 07:12:48
【问题描述】:
在我们的delphi源代码中:
class function TNetEncoding.GetBase64Encoding: TNetEncoding;
var
LEncoding: TBase64Encoding;
begin
if FBase64Encoding = nil then
begin
LEncoding := TBase64Encoding.Create;
if AtomicCmpExchange(Pointer(FBase64Encoding), Pointer(LEncoding), nil) <> nil then
LEncoding.Free
{$IFDEF AUTOREFCOUNT}
else
FBase64Encoding.__ObjAddRef
{$ENDIF AUTOREFCOUNT};
end;
Result := FBase64Encoding;
end;
但我不明白,它们混合了 原子操作(AtomicCmpExchange(Pointer(FBase64Encoding), Pointer(LEncoding), nil) 与 非原子操作,例如 if FBase64Encoding = nil then 和 Result := FBase64Encoding;
是不是搞错了?
【问题讨论】:
-
不,这不是一个错误。它是双重检查锁定的一种变体。但是,您允许线程推测性地创建单例,而不是锁定。如果两个线程创建对象,只有第一个成功,第二个销毁他们的新对象。
-
@DavidHeffernan: 但是如果一个线程正在执行 AtomicCmpExchange(Pointer(FBase64Encoding), Pointer(LEncoding), nil) 并且在完全相同的时刻另一个正在执行如果 FBase64Encoding = nil 并且此时只有一半指针的字节被写入 FBase64Encoding (在 64 位上,假设指针使用的总共 8 个字节中只写入了 4 个字节)所以 FBase64Encoding 不会是 nil 但也不会指向好的位置?跨度>
-
这解释了你关于 CocoaPointerConst 的 QP 报告 :-)
-
@DaveNottage 是的 :)
标签: delphi firemonkey