21xrx.com
2024-06-03 11:08:07 Monday
登录
文章检索 我的文章 写文章
C++中的线程安全单例模式
2023-07-03 11:39:44 深夜i     --     --
C++ 线程安全 单例模式

在多线程的环境下,单例模式是一种非常有用的设计模式。在C++中,单例模式可以通过静态成员变量来实现,但是需要注意线程安全性问题。如果不加措施,可能会导致多个线程同时执行单实例的初始化函数,进而破坏单例模式的设计要求。因此,在C++中实现线程安全的单例模式是一项很有挑战的任务。

下面给出一个例子,展示如何在C++中实现线程安全的单例模式。


class Singleton {

public:

  static Singleton& getInstance()

    static Singleton instance;

    return instance;

  

private:

  Singleton() {}

  ~Singleton() {}

  Singleton(const Singleton&);

  Singleton& operator=(const Singleton&);

};

在上述代码中,Singleton类的构造函数和析构函数都是私有的,这意味着不能在类外部创建Singleton实例,也不能对Singleton实例进行销毁。单例模式的唯一实例通过getInstance()方法返回,该方法使用static关键字声明,意味着可以通过Singleton::getInstance()的方式调用它。

上述代码看似简单,但实际上存在线程安全问题。当多个线程同时调用getInstance()方法时,可能会导致多个线程创建Singleton实例,违反了单例模式要求的唯一性。

为了解决这个问题,在C++11之前,可以使用锁来控制并发访问getInstance()方法,防止多个线程同时执行初始化操作。例如,可以使用pthread_mutex_lock()和pthread_mutex_unlock()函数实现线程安全的单例模式,如下所示:


class Singleton {

public:

  static Singleton& getInstance() {

    pthread_mutex_lock(&mutex_);

    static Singleton instance;

    pthread_mutex_unlock(&mutex_);

    return instance;

  }

private:

  Singleton() {}

  ~Singleton() {}

  Singleton(const Singleton&);

  Singleton& operator=(const Singleton&);

  static pthread_mutex_t mutex_;

};

pthread_mutex_t Singleton::mutex_ = PTHREAD_MUTEX_INITIALIZER;

在上述代码中,创建了一个名为mutex_的静态成员变量,该变量用于控制getInstance()方法的并发访问。在getInstance()方法的开头,使用pthread_mutex_lock()函数获取mutex_的互斥锁,保证只有一个线程同时执行初始化操作。在创建Singleton实例之后,使用pthread_mutex_unlock()函数释放mutex_的互斥锁,允许其他线程执行初始化操作。

在C++11之后,可以使用atomic变量来实现线程安全的单例模式,如下所示:


class Singleton {

public:

  static Singleton& getInstance() {

    static Singleton& instance = initInstance();

    return instance;

  }

private:

  Singleton() {}

  ~Singleton() {}

  Singleton(const Singleton&);

  Singleton& operator=(const Singleton&);

  static std::atomic<Singleton*> instance_;

  static Singleton& initInstance() {

    Singleton* p = new Singleton;

    instance_.store(p);

    return *p;

  }

};

std::atomic<Singleton*> Singleton::instance_(nullptr);

在上述代码中,创建了一个名为instance_的静态atomic 类型的变量,通过使用std::atomic<>()函数,确保instance_是原子类型的变量。instance_在getInstance()方法的内部进行初始化,使用initInstance()函数来生成唯一的实例。实现过程中使用了atomic::load()和atomic::store()函数来对instance_进行读写操作。

总的来说,C++中的线程安全单例模式需要注意并发访问的问题,根据不同的环境可以采用不同的解决方案,保证线程安全。

  
  

评论区

{{item['qq_nickname']}}
()
回复
回复