当前位置: 首页 > 知识库问答 >
问题:

单例线程安全类

林弘壮
2023-03-14

我在多线程环境中做的工作很少。所以,我需要知道below类的getInstance函数是否是线程安全的。这是单例类:

//Singleton class
class S {
  // intentionally avoided pointer
  static S singleObject;

   // Private constructor   
   s ();
   s (S &);
   s& operator= (const s&);
public:
  // return reference of static object
  s& getInstance ()
  {
    return singleObject;
  }

  /* Normally with static pointer instance, getInstnace look like as
   s& getInstace ()
   {
      // trying to avoid multiple copies of singleObject
      lock_mutex ()

       if (singleObject == null)
          singleObjecct = new S();

      unlock_mutex ();

      return *singleObject;
    }
  */
};

S S::singleObject;

在getInstance函数(未注释)中,返回静态对象的引用。它需要线程安全机制吗?

在第二个getInstance(注释)中,如果singleObject为null,我们就创建对象。所以,它需要锁定机制,需要同步,对吧?

共有3个答案

龙默
2023-03-14

除非您将 getInstance 声明为静态,否则您将无法调用它。这个错误几乎传播到所有回复。除此之外,我不能为所有答案添加更好的东西。

汝承载
2023-03-14

在 C 11 中,您可以将静态实例放在静态函数中:

class S
{
    private:
        S();
        S(S const&);
        S& operator=(S const&);

    public:
        static S& getInstance ()
        {
            static S singleObject;
            return singleObject;
        }
};

根据本标准第6.7.4段:

所有具有静态存储持续时间(3.7.1)或线程存储持续时间(3.7.2)的块范围变量的零初始化(8.5)在任何其他初始化发生之前执行。具有静态存储持续时间的块范围实体的常量初始化(3.6.2)在第一次进入其块之前执行(如果适用)。在允许实现在名称空间范围内静态初始化具有静态或线程存储持续时间的变量的相同条件下,允许实现使用静态或线程存储持续时间执行其他块范围变量的早期初始化(3.6.2)。否则,这样的变量在控制第一次通过其声明时被初始化;这种变量在其初始化完成时被认为是已初始化的。如果初始化通过引发异常退出,则初始化未完成,因此下次控件进入声明时将再次尝试初始化。如果控制在变量初始化的同时进入声明,则并发执行将等待初始化完成。如果在初始化变量时,控制递归地重新进入声明,则行为是未定义的。

宋志学
2023-03-14

在getInstance函数(未注释)中,返回静态对象的引用。它需要线程安全机制吗?

只要不在< code>main函数的生存期之外访问它,或者在其他线程可能进行非同步访问时修改它,那么从任何线程访问它都是安全的。

如果您在< code>main开始之前或结束之后进行访问(例如,从另一个静态对象的构造函数或析构函数中访问),那么就存在这样一种危险,即在那一点上它还没有被初始化,或者已经被销毁。这就是“懒惰初始化”的动机,比如你的第二个版本。

在第二个getInstance(注释)中,如果singleObject为null,我们就创建对象。所以,它需要锁定机制,需要同步,对吧?

是的,这需要一个锁定机制。对于支持 C 11(或类似)线程模型的编译器,像这样获取惰性初始化的更简单方法是使用函数静态变量,该变量将在首次进入范围时以线程安全的方式初始化:

S& getInstance ()
{
    static S singleObject;
    return singleObject;
}

这也将避免您的版本的内存泄漏,但是引入了一个危险,即它可能在其他静态对象之前被销毁;因此,从静态对象的析构函数访问是不安全的。

一般来说,C中的静态对象是这种死亡陷阱的雷区(无论您是否尝试将它们包装成某种单例反模式),最好避免。

 类似资料:
  • 问题内容: 我写了下面的Singleton类。我不确定这是否是线程安全的单例类吗? 谁能帮我这个?我在上述Singleton课堂上的任何想法都会有很大帮助。 更新代码: 我正在尝试将波希米亚建议纳入我的代码中。这是更新的代码,我得到了- 谁能看一下,让我知道这次是否正确? 问题答案: 但是有一个简单的技巧,可以让你的代码是线程安全的实现,并不需要同步!它称为“ 按需初始化持有人”习惯用法,它看起来

  • 问题内容: 有关Singletons的维基百科文章提到了一些用线程安全的方法来用Java实现结构。对于我的问题,让我们考虑具有冗长的初始化过程并且一次被多个线程访问的Singleton。 首先,这个未提及的方法是线程安全的吗?如果是的话,它在什么上进行同步? 其次,为什么以下实现线程安全且在初始化时是懒惰的?如果两个线程同时进入该方法,到底会发生什么? 最后,在第二个示例中,如果一个线程首先获取一

  • 我想知道Spring单例豆是否是线程安全的,如果是,那么为什么,如果不是,那么为什么? 因为我是初学者,所以帮助将不胜感激。

  • 我今天在思考这个问题。下面是我正在思考的一个场景。 singletonClassObj。添加两个数字(10,20); SingletonClassObj.addTwoNumbers(100,200); 现在我的问题是什么,假设Thread-1首先执行并调用方法。那么有没有可能在整个函数被线程-1执行之前,线程-2调用函数并更改x和y的值?例如,线程-1以10和20的形式发送数据,在将求和分配给变量

  • 静态编程语言单例(更具体地说,对象声明)在结构上是线程安全的吗?如果不是,用静态编程语言编写线程安全单例的最佳实践是什么? 我想是的,但我在文件中找不到任何明确的声明。

  • 本文向大家介绍枚举单例 线程安全-Java版相关面试题,主要包含被问及枚举单例 线程安全-Java版时的应答技巧和注意事项,需要的朋友参考一下 用枚举写单例实在太简单了!这也是它最大的优点。下面这段代码就是声明枚举实例的通常做法。 我们可以通过EasySingleton.INSTANCE来访问实例,这比调用getInstance()方法简单多了。创建枚举默认就是线程安全的,所以不需要担心doubl