EPr*_*und 2 delphi singleton multithreading synchronization delphi-6
要使用单例模式获取类的实例,我想使用以下函数:
这是草图
interface
uses SyncObjs;
type
TMCriticalSection = class(TCriticalSection)
private
Dummy : array [0..95] of Byte;
end;
var
InstanceNumber : Integer;
AObject: TObject;
CriticalSection: TMCriticalSection;
function getInstance: TObject;
implementation
uses Windows;
function getInstance: TObject;
begin
//I Want somehow use InterlockedCompareExchange instead of CriticalSession, for example
if InterlockedCompareExchange(InstanceNumber, 1, 0) > 0 then
begin
Result := AObject;
end
else
begin
CriticalSection.Enter;
try
AObject := TObject.Create;
finally
CriticalSection.Leave;
end;
InterlockedIncrement(InstanceNumber);
Result := AObject
end;
end;
initialization
CriticalSection := TMCriticalSection.Create;
InstanceNumber := 0;
finalization;
CriticalSection.Free;
end.
Run Code Online (Sandbox Code Playgroud)
三个问题:
1- 这种设计线程安全吗?尤其是与 InterlockedExchange 部分。
2- 如何使用 InterlockedCompareExchange?有可能做我正在尝试的事情吗?
3- 这种设计是否比涉及临界区范围内的所有代码更好?
备注:我的对象是线程安全的,只有我需要序列化的构造!
这不是完整的代码,只是重要的部分,我的意思是,getInstance 函数。
我需要使用某种单例对象。
有没有办法使用 InterlockedCompareExchange 来比较 InstanceNumber 的值是否为零?
和
1 - 仅在为 0 时创建对象,否则返回实例。
2 - 当值为 0 时:进入临界区。创建对象。离开临界区。
3 - 这样做会更好,而不是涉及关键部分范围内的所有代码?
interface
function getInstance: TObject;
implementation
var
AObject: TObject;
function getInstance: TObject;
var
newObject: TObject;
begin
if (AObject = nil) then
begin
//The object doesn't exist yet. Create one.
newObject := TObject.Create;
//It's possible another thread also created one.
//Only one of us will be able to set the AObject singleton variable
if InterlockedCompareExchangePointer(AObject, newObject, nil) <> nil then
begin
//The other beat us. Destroy our newly created object and use theirs.
newObject.Free;
end;
end;
Result := AObject;
end;
Run Code Online (Sandbox Code Playgroud)
的使用InterlockedCompareExchangePointer在操作周围建立了一个完整的内存屏障。有可能可以 InterlockedCompareExchangeRelease使用释放语义(以确保在执行比较交换之前完成对象的构造)。问题在于:
注意:任何发布到公共领域的代码。不需要归属。