采用RAII手法封转mutex使得mutex由栈上对象管理,能保证自动解锁不会重复解锁,加解锁在同一个线程,std::lock_guadr<>,std::unique_lock<>具备这样的功能,但是现在的g++还不支持c++11.
互斥量MutexLock的RAII封装:成员变量pthread_mutex_t mutex和pid_t holder。MutexLock调用pthread_mutex_init初始化mutex并holder=0;lock()调用pthread_mutex_init和holder为当前加锁线程id;unlock()调用pthread_mutex_unlock和将holder置为0;isLockedByThisThread()判断是否为本线程锁住;getPthreadMutex()返回mutex的指针;assertLocked()判断mutex是否锁住;设置friend class Condition#include<iostream> #include<pthread.h> #include<boost/utility.hpp> #include<string> #include<unistd.h> #include<stdexcept> using namespace std; using namespace boost; template<typename Mutex>//模板类封装 class _LockGuard:boost::noncopyable{ public: explicit _LockGuard(Mutex& m):m_(m){ m_.lock(); } ~_LockGuard(){ m_.unlock(); } private: Mutex &m_; }; class MutexLock:noncopyable{ public: MutexLock(){ pthread_mutex_init(&m_mutex,NULL); } ~MutexLock(){ pthread_mutex_destroy(&m_mutex); } void lock(){ pthread_mutex_lock(&m_mutex); } void unlock(){ pthread_mutex_unlock(&m_mutex); } private: pthread_mutex_t m_mutex; }; class MutexLockGuard:noncopyable{ public: explicit MutexLockGuard(MutexLock &mutex):m_mutex(mutex){ m_mutex.lock(); } ~MutexLockGuard(){ m_mutex.unlock(); } private: MutexLock &m_mutex; }; MutexLock lock; void print_even (int x) { if (x%2==0) std::cout << x << " is even\n"; else throw (std::logic_error("not even")); } void* print_thread_id (void *x) { int id=*(int*)x; try { // using a local lock_guard to lock mtx guarantees unlocking on destruction / exception: MutexLockGuard lck (lock); print_even(id); } catch (std::logic_error&) { std::cout << "[exception caught]\n"; } } void* _print_thread_id (void* x) { int id=*(int*) x; try { // using a local lock_guard to lock mtx guarantees unlocking on destruction / exception: _LockGuard<MutexLock> lck (lock); print_even(id); } catch (std::logic_error&) { std::cout << "[exception caught]\n"; } pthread_exit(0); } int main(){ pthread_t pid[10]; for(int i=0;i<10;i++){ if(pthread_create(&pid[i],NULL,print_thread_id,&i)<0)//_print_thread_id cout<<"pthread_create error"<<endl; } return 0; }
g++ -o raii_mutex raii_mutex.cpp -lpthread后执行结果可变,上面测试代码违背了不使用跨线程的mutex原则。
#include<iostream> #include<string> #include<unistd.h> #include<pthread.h> #include<assert.h> #include<boost/utility.hpp> using namespace std; using namespace boost; class Mutex:noncopyable{ public: Mutex(){ pthread_mutex_init(&mutex,NULL); } void lock(){ pthread_mutex_lock(&mutex); } void unlock(){ pthread_mutex_unlock(&mutex); } pthread_mutex_t& get(){ return mutex; } private: pthread_mutex_t mutex; }; class MutexLockGuard:noncopyable{ public: explicit MutexLockGuard(Mutex& mutex):mutex_(mutex){ mutex_.lock(); } ~MutexLockGuard(){ mutex_.unlock(); } private: Mutex& mutex_; }; class Condition:noncopyable{ public: explicit Condition(Mutex& mutex):mutex_(mutex){ pthread_cond_init(&pcond_,NULL); } ~Condition(){ pthread_cond_destroy(&pcond_); } void wait(){ pthread_cond_wait(&pcond_,&mutex_.get()); } void notify(){ pthread_cond_signal(&pcond_); } void notifyALL(){ pthread_cond_broadcast(&pcond_); } private: Mutex& mutex_; pthread_cond_t pcond_; }; class CountDownLatch{ public: CountDownLatch(int count):mutex_(),condition_(mutex_),count_(count){}//初始化顺序和成员声明一致 void wait(){ MutexLockGuard lock(mutex_); while(count_>0) condition_.wait(); } void countDown(){ MutexLockGuard lock(mutex_); --count_; if(count_==0) condition_.notifyALL(); } private: mutable Mutex mutex_;//注意声明顺序 Condition condition_; int count_; };