c++ 封裝線程庫 0
阿新 • • 發佈:2018-07-25
read public pri -c class pan lar bool __file__
1.互斥鎖簡介
互斥鎖主要用於互斥,互斥是一種競爭關系,用來保護臨界資源一次只被一個線程訪問。
POSIX Pthread提供下面函數用來操作互斥鎖。
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr); int pthread_mutex_lock(pthread_mutex_t *mutex); int pthread_mutex_trylock(pthread_mutex_t *mutex); int pthread_mutex_unlock(pthread_mutex_t *mutex);int pthread_mutex_destroy(pthread_mutex_t *mutex); //返回: //pthread_mutex_init總是返回0 //其他mutex函數返回0表示成功,非0的錯誤碼表示失敗
#define CHECK(exp) if(!exp) { fprintf(stderr, "File:%s, Line:%d Exp:[" #exp "] is true, abort.\n",__FILE__, __LINE__); abort(); }
由於pthread系列函數返回成功的時候都是0,因此,我們可以寫一個宏作為一個輕量級的檢查手段,來判斷處理錯誤。
實際使用的時候只需: CHECK(!pthread_mutex_lock(&mutex));
2.互斥鎖的封裝
需要考慮以下幾個問題:
a.互斥鎖的初始化與銷毀。
b.互斥鎖的操作:加鎖和釋放鎖。
另外,我們的自己封裝的類不應該有賦值和拷貝構造的語義,這一點跟單例模式類似,我們可以使我們的類繼承自boost庫的noncopyable。
//MutexLock.h
#ifndef __MUTEXLOCK_H__
#define __MUTEXLOCK_H__
#include <iostream>
#include <cstdio>
#include <boost/noncopyable.hpp>
#include <pthread.h>
#include <assert.h>
#define CHECK(exp) if(!exp) { fprintf(stderr, "File:%s, Line:%d Exp:[" #exp "] is true, abort.\n",__FILE__, __LINE__); abort();}
class MutexLock : public boost::noncopyable
{
friend class Condition;//條件變量友元聲明
public:
MutexLock();
~MutexLock();
void lock();
void unlock();
bool isLocking() const
{
return isLocking_;
}
pthread_mutex_t *getMutexPtr()
{
return &mutex_;
}
private:
void restoreMutexStatus()
{
isLocking_=true;
}
pthread_mutex_t mutex_;//互斥鎖
bool isLocking_;
};
#endif
這裏完成了MutexLock 類的聲明,但是這裏還需要一些補充,那就是使用RAII(資源獲取即初始化)技術,對MutexLock初始化和析構進行處理:初始化的時候加鎖,析構的時候解鎖,這就需要我們重新定義一個class MutexLockGuard
對MutexLock
進行操作
class MutexLockGuard:public boost::noncopyable
{
public:
MutexLockGuard(MutexLock &mutex):mutex_(mutex){ mutex_.lock();}//構造時加鎖
~MutexLockGuard()//析構時解鎖
{
mutex_.unlock();
}
private:
MutexLock &mutex_;//註意這裏為什麽是引用!!!!
};
下面就要具體實現幾個函數了,主要是: pthread_mutex_init()
、pthread_mutex_destroy()
、pthread_mutex_lock()
、pthread_mutex_unlock()
這四個函數的封裝:
#include "MutexLock.h"
MutexLock::MutexLock():isLocking_(false)
{
CHECK(!pthread_mutex_init(&mutex_,NULL));
}
MutexLock::~MutexLock()
{
assert(!isLocking());
CHECK(!pthread_mutex_destroy(&mutex_));
}
void MutexLock::lock()
{
CHECK(!pthread_mutex_lock(&mutex_))//先加鎖再修改狀態,保證以下賦值操作的原子性。
isLocking_=true;
}
void MutexLock::unlock()
{
isLocking_=false;//先修改狀態在解鎖,保證賦值操作的原子性。
CHECK(!pthread_mutex_unlock(&mutex_));
}
封裝以後,我們使用:
MutexLockGurad lock(mutex);//就是 MutexLock對象被另一個對象管理
對臨界區進行加鎖,而只要我們控制好lock
變量的生存期,就能控制臨界區,例如:
int count=0;
{
MutexLockGurad lock(mutex);
count++;
}//臨界區
//...
//離開lock的作用域,lock作為棧上變量,自動釋放,調用析構函數,同時釋放鎖。
c++ 封裝線程庫 0