线程安全的单例模式-以C++代码为例

来源:互联网 发布:淘宝店铺logo在线制作 编辑:程序博客网 时间:2024/05/20 19:46

本文描述3种场景下的单例模式:

  • 进程体内无线程的单例模式
  • 进程体内多线程单例模式
  • 在单个线程体中的单例模式

本文所写单例模式代码都使用懒汉模式。

进程体内单例

注意问题:

  • 如果进程体中运行多个线程,则需要考虑多线程同步和互斥的问题。
  • 如果进程体重没有运行多个线程,则不需要考虑多线程同步和互斥
  • 使用线程互斥锁保证多进程同步

使用场景举例 :

  • 日志类、文件读写类
  • 资源管理类

代码示例:

进程体内没有运行多线程的单例模式,无需考虑线程同步与互斥

class Singleton {  public:    static Singleton* getInstance() {        if (NULL == instance) {          instance = new SingletonInside();        }        return instance;    }  private:    SingletonInside(){}    ~SingletonInside() {}    static Singleton* instance;};Singleton::instance = NULL;    

进程体内运行多线程单例模式,使用系统mutex保证线程安全

class Singleton {  public:    static Singleton* getInstance() {        pthread_once(&g_once_control, InitOnce);        pthread_mutex_lock(&mutex);  // lock        if (NULL == instance) {          instance = new SingletonInside();        }        pthread_mutex_unlock(&mutex); // unlock        return instance;    }  private:    SingletonInside() {    }    ~SingletonInside() {       pthread_mutex_destroy(&mutex);   // destroy lock    }    static void InitOnce(void) {      pthread_mutex_init(&mutex,NULL);  // init lock    }    Singleton* instance;    static pthread_once_t g_once_control;    static pthread_mutex_t mutex;};Singleton::instance = NULL;pthread_once_t Singleton::g_once_control = PTHREAD_ONCE_INIT;

单个线程体中的单例

某些资源在单个线程体内需要保持单例,即每个线程体内都保持唯一。每个线程体内,对象相互隔离,则无需考虑线程安全问题。

此种单例模式的实例需要调用系统提供的 TLS 接口,放于线程局部存储中。

使用场景举例:

  • 多路复用Socket封装类
  • 网络上下文环境类
  • 线程安全的资源

代码示例

class Singleton {  public:    static Singleton* getInstance() {       pthread_once(&g_once_control, InitOnce);       instance = (Singleton*)pthread_getspecific(g_thread_data_key);        if (NULL == instance) {          instance = new SingletonInside();          pthread_setspecific(g_thread_data_key, (void*)Singleton)        }        return instance;    }  private:    SingletonInside() : instance(NULL){}    ~SingletonInside() {       pthread_key_delete(g_thread_data_key);    }    static void InitOnce(void) {      pthread_key_create(&g_thread_data_key, NULL);    }    Singleton* instance;    static pthread_once_t g_once_control;    static pthread_key_t g_thread_data_key;};pthread_once_t Singleton::g_once_control = PTHREAD_ONCE_INIT;pthread_key_t Singleton::g_thread_data_key;

如果使用 Poco库 TreadLocal ,代码还会简洁很多,性能上也会好很多

    class Singleton {      public:        static Singleton* getInstance() {            if (NULL == instance) {              instance = new SingletonInside();            }            return instance;        }      private:        SingletonInside() {}        ~SingletonInside() {           delete instance;        }        static Poco::ThreadLocal<Singleton> instance;    };Poco::ThreadLocal<singleton> Singleton::instance = NULL;

总结

  • 无论程序是多进程运行还是多线程运行,代码都要尽量兼容线程安全
转载请注明来源
博客首页:作程的技术博客
文章标题:《线程安全的单例模式-以C++代码为例》
本文链接:http://it.zuocheng.net/thread-safe-singleton-pattern-cpp-zh
0 0