ITPub博客

首页 > 应用开发 > IT综合 > C++中多线程Singleton的实现

C++中多线程Singleton的实现

IT综合 作者:下一站在哪 时间:2014-06-06 10:49:44 0 删除 编辑

  我想关于Singleton模式的实现和资料很多很多,这里为什么专门拿出来写一写,还是因为个人觉得要想把单例模式写好还真不是一件容易的事情。

  其中涉及到不少编译和底层的知识。这里以Linux平台为例,这是因为本人对windows下的编程实在不太熟悉。

  本文所有代码均上传至github仓库:https://github.com/kevin-shanghai/Programming_Practice

  如果有兴趣,可以随意获取,本代码仅用于测试,如用于生产环境发生任何问题,本人概不负责。

  本文针对于线程安全的Singleton实现,并基于模板,这样通用性更好,否则对于每个类都要实现自己的单例模式。

  一般的单线程下的Singleton实现非常简单,郑州牛皮癣医院用一个静态成员函数返回该类的一个实例就行了,但是遇到多线程,事情就麻烦了不少。

  废话少说,下面看下具体代码:

  点击(此处)折叠或打开/**********************************************

  ******* g++ test.cpp -lpthread****************

  * *******************************************/

  #include

  #include

  using namespace std;

  template

  class Singleton

  {

  public:

  Singleton()

  {

  }

  static T* GetInstance()

  {

  if(m_pInstance == NULL)

  {

  pthread_mutex_lock(&mutex);

  if(m_pInstance == NULL)

  {

  T* temp = new T;

  m_pInstance = temp;

  }

  pthread_mutex_unlock(&mutex);

  }

  return m_pInstance;

  }

  private:

  static T* m_pInstance;

  static pthread_mutex_t mutex;

  };

  template

  T* Singleton::m_pInstance = NULL;

  template

  pthread_mutex_t Singleton::mutex;

  class Test:public Singleton

  {

  public:

  Test()

  {

  cout<<"Test::Test()."<

  }

  };

  void* thread1(void*)

  {

  cout<<"In thread1."<

  Test* test1 = Test::GetInstance();

  }

  void* thread2(void *)

  {

  cout<<"In thread2."<

  Test* test2 = Test::GetInstance();

  }

  int main()

  {

  const unsigned int thread_num = 20;

  pthread_t thread_id[thread_num];

  for(unsigned int i = 0; i

  {

  pthread_create(&thread_id[i], NULL, thread1, NULL);

  }

  for(unsigned int i = 0; i

  {

  pthread_create(&thread_id[i], NULL, thread2, NULL);

  }

  sleep(1);

  return 0;

  }

  可以看到上面的代码中使用了double-check机制,也就是对m_pInstance检查了两遍,这样有利于提高性能。还有一点需要注意的是

  T* temp = new T; m_pInstance = temp;而没有直接用m_pInstance = new T;这是因为这一语句将会分为三步来执行:

  1. 非配内存

  2. 用相应的实例初始化该内存区域

  3. 将该内存地址赋值给该指针m_pInstance

  如果其中第2步骤和第3步或者第一步骤颠倒了,郑州最好的牛皮癣医院也就是编译器对我们的代码进行了优化,那么赋值给m_pInsannce指针的就是没有初始化的

  所以我们用一个临时变量解决这个问题

  其实Linux平台下的singleton模式有更简单的实现方式,主要是利用pthread_once这个api,看代码:

  点击(此处)折叠或打开#include

  #include

  using namespace std;

  template

  class Singleton

  {

  public:

  static T& instance()

  {

  pthread_once(&m_Once, &Singleton::init);

  return *m_tValue;

  }

  private:

  Singleton();

  ~Singleton();

  static void init()

  {

  m_tValue = new T();

  }

  private:

  static pthread_once_t m_Once;

  static T* m_tValue;

  };

  template

  pthread_once_t Singleton::m_Once = PTHREAD_ONCE_INIT;

  template

  T* Singleton::m_tValue = NULL;

  class Test

  {

  public:

  Test()

  {

  cout<<"In Test::Test()."<

  }

  };

  void* thread_func(void*)

  {

  Test& t = Singleton::instance();

  }

  int main(int argc, char const *argv[])

  {

  // Test& t = Singleton::instance();

  pthread_t thread_id[10];

  for(int i=0;i<10;i++)

  {

  pthread_create(&thread_id[i], NULL, thread_func, NULL);

  }

  return 0;

  }

  其实这种方式在Linux平台下比较简单,pthread_once保证Init函数只执行一次,建议Linux下大家用这种方法来实现。

  这种单件模式比较通用,而且在多线程环境下也很稳定,如果大家要实现跨平台的singleton模式,那么可以加上相应平台的

  创建线程的api就可以了。

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/29661313/viewspace-1176783/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2014-05-16

  • 博文量
    24
  • 访问量
    43693