21xrx.com
2024-12-23 00:52:50 Monday
登录
文章检索 我的文章 写文章
C++实现线程安全的单例模式
2023-06-24 10:39:04 深夜i     --     --
C++ 线程安全 单例模式

单例模式是一种常用的设计模式,它可以保证一个类只有一个实例,并且全局可访问。然而,在多线程环境下使用单例模式可能会导致多个线程同时访问同一个实例,从而出现竞争条件。为了解决这个问题,需要实现线程安全的单例模式。

C++语言提供了多种方式来实现线程安全的单例模式,其中最常见的方式是懒汉式和饿汉式。

懒汉式是在第一次访问实例时才进行实例化,因此也称为延迟加载。实现懒汉式线程安全的单例模式的关键是在实例化时使用互斥锁来防止多线程访问同一个实例。

以下是使用懒汉式实现线程安全的单例模式的示例代码:


class Singleton {

public:

  static Singleton* getInstance() {

    if (instance == nullptr) {

      std::unique_lock<std::mutex> lock(mtx);

      if (instance == nullptr) {

        instance = new Singleton();

      }

    }

    return instance;

  }

  // 禁止复制和移动

  Singleton(const Singleton&) = delete;

  Singleton& operator=(const Singleton&) = delete;

  Singleton(Singleton&&) = delete;

  Singleton& operator=(Singleton&&) = delete;

private:

  Singleton() {}

  static Singleton* instance;

  static std::mutex mtx;

};

Singleton* Singleton::instance = nullptr;

std::mutex Singleton::mtx;

在上面的示例代码中,getInstance()方法是获取单例的静态方法。在实例化时,使用了std::unique_lock 来获取互斥锁。当instance为nullptr时,只有一个线程能够获得锁并且进行实例化,而其他线程必须等待该线程释放锁后才能进入getInstance()方法。

另外,上述代码还禁止了单例的复制和移动,以防止出现多个实例。

饿汉式是在程序启动时即进行实例化,因此也称为预加载。使用饿汉式线程安全的单例模式时,需要在定义静态实例时使用互斥锁。

以下是使用饿汉式实现线程安全的单例模式的示例代码:


class Singleton {

public:

  static Singleton* getInstance()

    return instance;

  

  // 禁止复制和移动

  Singleton(const Singleton&) = delete;

  Singleton& operator=(const Singleton&) = delete;

  Singleton(Singleton&&) = delete;

  Singleton& operator=(Singleton&&) = delete;

private:

  Singleton() {}

  static Singleton* instance;

  static std::mutex mtx;

};

Singleton* Singleton::instance = new Singleton();

std::mutex Singleton::mtx;

在上面的示例代码中,instance为静态实例,在定义时使用了std::unique_lock 来获取互斥锁,并且第一个线程完成初始化后,其他线程只能使用已经完成初始化的实例。

总之,无论是懒汉式还是饿汉式,都需要使用互斥锁来保证线程安全,避免出现竞争条件。使用单例模式可以有效地控制对象的创建和访问,从而提高系统的效率和安全性。

  
  

评论区

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