项目中需要在多线程环境下,输出日志到标准输出,以下是实现过程。
首先,我们需要一个锁类,能够自动初始化,并且降低耦合。
- /*
- * locker.h
- *
- * Created on: Apr 14, 2012
- * Author: joan
- */
-
- #ifndef LOCKER_H_
- #define LOCKER_H_
-
- #include "../OPTION.h"
-
- class locker
- {
- public:
- inline locker(){ pthread_mutex_init(&mutex,NULL);}
- inline ~locker(){ pthread_mutex_destroy(&mutex);}
- inline void lock(){ pthread_mutex_lock(&mutex);}
- inline void unlock(){ pthread_mutex_unlock(&mutex);}
- private:
- pthread_mutex_t mutex;
- };
-
- #endif /* LOCKER_H_ */
- /*
- * log.h
- *
- * Created on: Apr 8, 2012
- * Author: joan
- */
-
- #ifndef LOG_H_
- #define LOG_H_
-
- #include "../OPTION.h"
- #include "locker.h"
-
- /*
- * this class is responsible for the running log of tinyJSE
- * there should only exist one instance of tinyLog,
- * so we use singleton to implement tinyLog
- */
- class tinyLog
- {
- public:
- static tinyLog *GetInstance();
- static void WriteLog(const char *FORMAT,...);
- private:
- tinyLog();
- ~tinyLog();
- private:
- static tinyLog *log;
- static locker llock;
- };
- #endif /* LOG_H_ */
然后是日志类的实现,注意全局访问点中使用double check提高性能。
- /*
- * log.cpp
- *
- * Created on: Apr 8, 2012
- * Author: joan
- */
-
- #include "../OPTION.h"
- #include "log.h"
-
- tinyLog * tinyLog::log = NULL;
- locker tinyLog::llock;
-
- tinyLog::tinyLog()
- {
- }
-
- tinyLog::~tinyLog()
- {
- }
-
- /*
- * get the pointer to the only instance of tinyLog
- * use double check to assure only one instance is created
- */
- tinyLog *tinyLog::GetInstance()
- {
- if(NULL == log)
- {//double check
- llock.lock();
- if(NULL == log)
- {
- log = new tinyLog(); //这里最好换成{ tinyLog * tmpLog=new tinyLog(); log=tmpLog; } 原因请看我另外一篇"C++中多线程Singleton的实现"
- }
- llock.unlock();
- }
- return log;
- }
-
- /*
- * Unified handling of the log of tinyJSE
- */
- void tinyLog::WriteLog(const char *FORMAT,...)
- {
- va_list args;
-
- va_start(args, FORMAT);
-
- llock.lock();
-
- vfprintf(stdout,FORMAT,args);
-
- llock.unlock();
-
- va_end(args);
-
- }
- #define PRINT(FORMAT,args...) tinyLog::GetInstance()->WriteLog(FORMAT,##args)
转: http://blog.csdn.net/joanlynnlove/article/details/7462254
但是自己在用上面的程序中发现, 当同一个线程中调用了两次Locker::Lock()时, 会产生死锁的情况,原因是它用的互斥量是标准的互斥量类型, 并不做任何特殊的错误检查或死锁检测,在同一个线程中调用两次加锁时, 就由于第一次加锁还没有释放,就变成死锁了. 要将mutex的类型属性设置为PTHREAD_MUTEX_RECURSIVE,这种类型的互斥量允许同一线程在互斥量解锁之前对该互斥量进行多次加锁.
(APUE中有说明).
那么lock定义如下:
- class Locker
- {
- public:
- inline Locker()
- {
- pthread_mutexattr_t attr;
- pthread_mutexattr_init(&attr);
- int err;
- if(0 != (err=pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE)))
- {
- printf("pthread_mutexattr_settype error. mutexattr addr=%x\n",(unsigned)this);
- }
- pthread_mutex_init(&mutex,&attr);
- pthread_mutexattr_destroy(&attr);
- }
- inline ~Locker(){ pthread_mutex_destroy(&mutex);}
- inline void Lock()
- {
-
- pthread_mutex_lock(&mutex);
- }
- inline void Unlock()
- {
- pthread_mutex_unlock(&mutex);
- }
- private:
- pthread_mutex_t mutex;
- };