#ifndef _MULTITHREAD_H_ #define _MULTITHREAD_H_ #include <pthread.h> #include <assert.h> #include <errno.h> class MutexLock { public: MutexLock():holder_(0) { int iret = pthread_mutex_init(&mutex_,NULL); assert(0 == iret);(void) iret; } ~MutexLock() { assert(0 == holder_);//when destroy non lock int iret = pthread_mutex_destroy(&mutex_); assert(0 == iret);(void) iret; } /*bool isLockedByThisThread() { return holder_ == CurrentThread::tid(); } void assertLocked() { assert(isLockedByThisThread() ); }*/ protected: //internal usage void lock() { pthread_mutex_lock(&mutex_); //holder_ = CurrentThread::tid(); } void unlock() { holder_ = 0; pthread_mutex_unlock(&mutex_); } pthread_mutex_t* getPthreadMutex() /*non-const*/ { return &mutex_; } private: pthread_mutex_t mutex_; pid_t holder_; }; class MutexLockGuard { public: explicit MutexLockGuard(MutexLock& mutex):mutex_(mutex) { mutex_.lock(); } ~MutexLockGuard() { mutex_.unlock(); } private: MutexLock& mutex_; }; //prevent misuse like: //MutexLockGuard(mutex_); 遗漏变量名,产生一个临时变量又马上销毁了 //right method: MutexLockGuard guard(mutex_); #define MutexLockGuard(x) error "Missing guard object name" class Condition { public: explicit Condition(MutexLock& mutex):mutex_(mutex) { pthread_cond_init(&pcond_,NULL); } ~Condition() { pthread_cond_destroy(&pcond_); } void wait() { pthread_cond_wait(&pcond_,mutex_.getPthreadMutex() ); } bool waitForSeconds(int second) { /* struct timespct{ * time_t tv_sec; * long tv_nsec; * }; * */ struct timespec abstime; /*clock_gettime 提供纳秒的精确度 *int clock_gettime(clockid_t clk_id, struct timespec* tp); *clockid_t用于指定计时时钟的类型: *CLOCK_REALTIME,系统实时时间,随着系统实时时间改变而改变,从UTC1970-1-1 0:0:0开始计时,中间如果系统时间更改,则对应的时间相应改变 *CLOCK_MONOTONIC,从系统启动这一刻起开始计时,不受系统时间被用户改变的影响 *CLOCK_PROCESS_CPUTIME_ID,本进程到当前代码系统CPU花费时间 *CLOCK_THREAD_CPUTIME_ID,线程CPU时间 */ clock_gettime(CLOCK_REALTIME,&abstime); abstime.tv_sec += second; return ETIMEDOUT == pthread_cond_timedwait(&pcond_,mutex_.getPthreadMutex(),&abstime); } void notify() { pthread_cond_signal(&pcond_); } void notifyAll() { pthread_cond_broadcast(&pcond_); } private: MutexLock& mutex_; pthread_cond_t pcond_; }; #endif //_MULTITHREAD_H_
下面给出一个简单用法,用于构造一个简单的同步阻塞队列。
#include "MultiThread.h" #include <deque> #include <assert.h> template<typename T> class BlockingQueue { public: BlockingQueue() :mutex_(), notEmpty_(), queue_() { } ~BlockingQueue() { } void put(const T& x) { MutexLockGuard lock(mutex_);//局部作用域正好是临界区 queue_.push_back(x); notEmpty_.notify(); } T take() { MutexLockGuard lock(mutex_); //while判断,因为可能被意外唤醒,"惊群" while(queue_.empty() ) { notEmpty_.wait(); } assert(!queue_.empty() ); T front(queue_.front() ); queue_.pop_front(); return front; } size_t size() { MutexLockGuard lock(); return queue_.size(); } private: mutable MutexLock mutex_; Condition notEmpty_; std::deque<T> queue_; };
通过上面例子我们可以看到简单封装的便捷使用,其中MutexLockGuard使用栈上空间,其局部作用域正好是临界区。该队列是线程安全的,我们将同步做到队列内部,避免外部线程分别加锁,降低了复杂性。