获取 Singleton 类 Instance Multithread [英] Aquire Singleton class Instance Multithread
问题描述
要获得具有单例模式的类的实例,我想使用以下函数:
To get the instance of the class with Singleton pattern, I want use the following function:
这是草图
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.
三个问题:
1- 这种设计是线程安全的吗?尤其是带有 InterlockedExchange 的部分.
2- 如何使用 InterlockedCompareExchange?有可能做我正在尝试的事情吗?
3- 这种设计是否比包含关键部分范围内的所有代码更好?
1- Is this design Thread Safe? Especially the with InterlockedExchange Part.
2- How to use the InterlockedCompareExchange? Is it possible to do what i'm trying?
3- Is this design better than involve all code within the critical section scope?
备注:我的对象是线程安全的,只有我需要序列化的构造!
这不是内部代码,只是重要的部分,我的意思是 getInstance 函数.
我需要使用某种单例对象.
如果 InstanceNumber 的值为零,有什么方法可以使用 InterlockedCompareExchange 进行比较?
和
1 - 仅当为 0 时才创建对象,否则返回实例.
2 - 当值为 0 时:进入临界区.创建对象.离开临界区.
3 - 这样做会更好,而不是涉及关键部分范围内的所有代码?
I NEED to use some kind of singleton object.
Is there any way to use InterlockedCompareExchange to compare if the value of InstanceNumber is zero?
And
1 - Create the object only when is 0, otherwise, return the instance.
2 - When the value is 0: Enter in the critical section. Create the object. Leave critical section.
3 - Would be better to do this way, instead of involve all code within the critical section scope?
推荐答案
您的设计不起作用,即使不了解 InterlockedCompareExchange
的作用,也可以看出这一点.事实上,不管 InterlockedCompareExchange
的含义如何,你的代码都被破坏了.
Your design does not work and this can be seen even without any understanding of what InterlockedCompareExchange
does. In fact, irrespective of the meaning of InterlockedCompareExchange
, your code is broken.
要看到这一点,请考虑两个线程同时到达 getInstance
中的 if
语句.让我们考虑他们采取哪些分支的三个选项:
To see this, consider two threads arriving at the if
statement in getInstance
at the same time. Let's consider the three options for which branches they take:
- 他们都选择了第二个分支.然后您创建两个实例,您的代码不再实现单例.
- 他们都选择了第一个分支.那么你永远不会创建实例.
- 一个选择第一个,另一个选择第二个.但是由于第一个分支中没有锁,因此采用该路由的线程可以在其他线程写入之前读取
AObject
.
我个人会使用 double-如果我必须实现您的 getInstance
函数,请检查锁定.
Personally I'd use double-checked locking if I had to implement your getInstance
function.
这篇关于获取 Singleton 类 Instance Multithread的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!