获取单例类实例多线程 [英] Aquire Singleton class Instance Multithread

查看:162
本文介绍了获取单例类实例多线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

要获取具有Singleton模式的类的实例,我想使用以下函数:

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函数.

Remark: My object is thread safe, only the construction i need to serialize!
This is not the intire code, only the important part, i mean, the getInstance function.

需要使用某种单例对象.
如果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:

  1. 他们都选择第二个分支.然后,您创建两个实例,您的代码不再实现单例.
  2. 他们都选择第一个分支.然后,您再也不会创建实例.
  3. 一个选择第一个,另一个选择第二个.但是,由于第一个分支没有锁,因此采用该路由的线程可以在另一个线程写入AObject之前读取它.
  1. They both choose the second branch. Then you create two instances and your code no longer implements a singleton.
  2. They both choose the first branch. Then you never create an instance.
  3. One choose the first and the other chooses the second. But since there is no lock in the first branch, the thread that takes that route can read AObject before the other thread has written it.

我个人会使用 double-如果必须执行您的getInstance函数,请检查锁定.

Personally I'd use double-checked locking if I had to implement your getInstance function.

这篇关于获取单例类实例多线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆