【转】单例模式 C++实现 多线程安全

转自:http://blog.csdn.net/joanlynnlove/article/details/7462254

项目中需要在多线程环境下,输出日志到标准输出,以下是实现过程。

首先,我们需要一个锁类,能够自动初始化,并且降低耦合。

  1. /* 
  2.  * locker.h 
  3.  * 
  4.  *  Created on: Apr 14, 2012 
  5.  *      Author: joan 
  6.  */  
  7.   
  8. #ifndef LOCKER_H_  
  9. #define LOCKER_H_  
  10.   
  11. #include "../OPTION.h"  
  12.   
  13. class locker  
  14. {  
  15. public:  
  16.     inline locker(){        pthread_mutex_init(&mutex,NULL);}  
  17.     inline ~locker(){       pthread_mutex_destroy(&mutex);}  
  18.     inline void lock(){     pthread_mutex_lock(&mutex);}  
  19.     inline void unlock(){   pthread_mutex_unlock(&mutex);}  
  20. private:  
  21.     pthread_mutex_t mutex;  
  22. };  
  23.   
  24. #endif /* LOCKER_H_ */  

其次,声明日志类,重点是将构造函数私有化,将函数成员和数据成员声明为静态,添加实例指针和全局访问点。

  1. /* 
  2.  * log.h 
  3.  * 
  4.  *  Created on: Apr 8, 2012 
  5.  *      Author: joan 
  6.  */  
  7.   
  8. #ifndef LOG_H_  
  9. #define LOG_H_  
  10.   
  11. #include "../OPTION.h"  
  12. #include "locker.h"  
  13.   
  14. /* 
  15.  * this class is responsible for the running log of tinyJSE 
  16.  * there should only exist one instance of tinyLog, 
  17.  * so we use singleton to implement tinyLog 
  18.  */  
  19. class tinyLog  
  20. {  
  21. public:  
  22.     static tinyLog *GetInstance();  
  23.     static void WriteLog(const char *FORMAT,...);  
  24. private:  
  25.     tinyLog();  
  26.     ~tinyLog();  
  27. private:  
  28.         static tinyLog *log;  
  29. static locker llock;  
  30. };  
  31. #endif /* LOG_H_ */  

然后是日志类的实现,注意全局访问点中使用double check提高性能。

  1. /* 
  2.  * log.cpp 
  3.  * 
  4.  *  Created on: Apr 8, 2012 
  5.  *      Author: joan 
  6.  */  
  7.   
  8. #include "../OPTION.h"  
  9. #include "log.h"  
  10.   
  11. tinyLog * tinyLog::log = NULL;  
  12. locker tinyLog::llock;  
  13.   
  14. tinyLog::tinyLog()  
  15. {  
  16. }  
  17.   
  18. tinyLog::~tinyLog()  
  19. {  
  20. }  
  21.   
  22. /* 
  23.  * get the pointer to the only instance of tinyLog 
  24.  * use double check to assure only one instance is created 
  25.  */  
  26. tinyLog *tinyLog::GetInstance()  
  27. {  
  28.     if(NULL == log)  
  29.     {//double check  
  30.         llock.lock();  
  31.         if(NULL == log)  
  32.         {  
  33.             log = new tinyLog();  
  34.         }  
  35.         llock.unlock();  
  36.     }  
  37.     return log;  
  38. }  
  39.   
  40. /* 
  41.  * Unified handling of the log of tinyJSE 
  42.  */  
  43. void tinyLog::WriteLog(const char *FORMAT,...)  
  44. {  
  45.     va_list args;  
  46.   
  47.     va_start(args, FORMAT);  
  48.   
  49.     llock.lock();  
  50.   
  51.     vfprintf(stdout,FORMAT,args);  
  52.   
  53.     llock.unlock();  
  54.   
  55.     va_end(args);  
  56.   
  57. }  

使用该单例:

  1. #define PRINT(FORMAT,args...)   tinyLog::GetInstance()->WriteLog(FORMAT,##args)  
原文地址:https://www.cnblogs.com/wenshanzh/p/2831312.html