線程鎖的封裝
線程鎖的基本操作:
1. 創建鎖 int pthread_mutex_init(pthread_mutex_t*mutex, const pthread_mutexattr_t * attr);
attr:創建鎖的屬性。一般默認爲NULL,分爲以下幾個屬性:
* PTHREAD_MUTEX_TIMED_NP,這是缺省值,也就是普通鎖。當一個線程加鎖以後,其餘請求鎖的線程將形成一個等待隊列,並在解鎖後按優先級獲得鎖。這種鎖策略保證了資源分配的公平性;
* PTHREAD_MUTEX_RECURSIVE_NP,嵌套鎖,允許同一個線程對同一個鎖成功獲得多次,並通過多次unlock解鎖。如果是不同線程請求,則在加鎖線程解鎖時重新競爭;
* PTHREAD_MUTEX_ERRORCHECK_NP,檢錯鎖,如果同一個線程請求同一個鎖,則返回EDEADLK,否則與PTHREAD_MUTEX_TIMED_NP類型動作相同。這樣就保證當不允許多次加鎖時不會出現最簡單情況下的死鎖;
* PTHREAD_MUTEX_ADAPTIVE_NP,適應鎖,動作最簡單的鎖類型,僅等待解鎖後重新競爭;
2. 加鎖 int pthread_mutex_lock(pthread_mutex_t*mutex);
3. 解鎖 int pthread_mutex_unlock(pthread_mutex_t *mutex);
4. 嘗試鎖 int pthread_mutex_trylock(pthread_mutex_t *mutex); //鎖被佔用返回EBUSY,而非等待
5. 鎖銷燬 int pthread_mutexattr_destroy (pthread_mutex_t *mutex);
線程鎖的封裝
線程鎖異常
struct YR_ThreadMutex_Exception : public YR_Lock_Exception
{
YR_ThreadMutex_Exception(const string &buffer) : YR_Lock_Exception(buffer){};
YR_ThreadMutex_Exception(const string &buffer, int err) : YR_Lock_Exception(buffer, err){};
~YR_ThreadMutex_Exception() throw() {};
};
線程鎖的定義
class YR_ThreadMutex
{
public:
YR_ThreadMutex();
virtual ~YR_ThreadMutex();
//加鎖
void lock() const;
//解鎖
void unlock() const;
//嘗試鎖
bool tryLock() const;
protected:
mutable pthread_mutex_t _mutex; //創建線程鎖
};
實現
鎖的初始化可以放在構造函數裏,這裏分爲四步來初始化線程鎖_mutex
:
YR_ThreadMutex::YR_ThreadMutex()
{
int rc;
pthread_mutexattr_t attr; //1. 創建線程鎖屬性對象
rc = pthread_mutexattr_init(&attr); //初始化鎖屬性對象
assert(rc == 0);
//2. 將鎖屬性中的鎖類型設爲檢錯鎖
rc = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
assert(rc == 0);
//3. 初始化鎖對象
rc = pthread_mutex_init(&_mutex, &attr);
assert(rc == 0);
//4. 銷燬鎖屬性對象
rc = pthread_mutexattr_destroy(&attr);
assert(rc == 0);
//如果操作不成功,則拋出異常
if(rc != 0)
{
throw TC_ThreadMutex_Exception("[TC_ThreadMutex::TC_ThreadMutex] pthread_mutexattr_init error", rc);
}
}
線程鎖在析構函數中銷燬:
YR_ThreadMutex::~YR_ThreadMutex()
{
int rc = 0;
rc = pthread_mutex_destroy(&_mutex);
if(rc != 0)
{
cerr << "[YR_ThreadMutex::~YR_ThreadMutex] pthread_mutex_destroy error:" << string(strerror(rc)) << endl;
}
}
加鎖
void YR_ThreadMutex::lock() const
{
int rc = pthread_mutex_lock(&_mutex);
if(rc != 0)
{
if(rc == EDEADLK) //如果當前線程已經擁有線程鎖
{
throw YR_ThreadMutex_Exception("[YR_ThreadMutex::lock] pthread_mutex_lock dead lock error", rc);
}
else
{
throw YR_ThreadMutex_Exception("[YR_ThreadMutex::lock] pthread_mutex_lock error", rc);
}
}
}
解鎖
void YR_ThreadMutex::unlock() const
{
int rc = pthread_mutex_unlock(&_mutex);
if(rc != 0)
{
throw YR_ThreadMutex_Exception("[YR_ThreadMutex::unlock] pthread_mutex_unlock error", rc);
}
}
嘗試鎖
bool YR_ThreadMutex::tryLock() const
{
int rc = pthread_mutex_trylock(&_mutex);
if(rc != 0 && rc != EBUSY) //如果所佔用則返回EBUSY
{
if(rc == EDEADLK) //如果當前線程已經擁有線程鎖
{
throw YR_ThreadMutex_Exception("[YR_ThreadMutex::tryLock] pthread_mutex_trylock dead lock error", rc);
}
else
{
throw YR_ThreadMutex_Exception("[YR_ThreadMutex::tryLock] pthread_mutex_trylock error", rc);
}
}
return (rc == 0);
}
嵌套鎖的封裝
嵌套鎖的定義
class YR_ThreadRecMutex
{
public:
/**
* @brief 構造函數
*/
YR_ThreadRecMutex();
/**
* @brief 析夠函數
*/
virtual ~YR_ThreadRecMutex();
/**
* @brief 鎖, 調用pthread_mutex_lock.
*
* return : 返回pthread_mutex_lock的返回值
*/
int lock() const;
/**
* @brief 解鎖, pthread_mutex_unlock.
*
* return : 返回pthread_mutex_lock的返回值
*/
int unlock() const;
/**
* @brief 嘗試鎖, 失敗拋出異常.
*
* return : true, 成功鎖; false 其他線程已經鎖了
*/
bool tryLock() const;
/**
* @brief 加鎖後調用unlock是否會解鎖, 給TC_Monitor使用的
*
* @return bool
*/
bool willUnlock() const;
protected:
/**
* @brief 友元類
*/
friend class TC_ThreadCond;
/**
* @brief 計數
*/
int count() const;
/**
* @brief 計數
*/
void count(int c) const;
private:
/**
鎖對象
*/
mutable pthread_mutex_t _mutex;
mutable int _count;
};
實現
YR_ThreadRecMutex::YR_ThreadRecMutex()
: _count(0)
{
int rc;
pthread_mutexattr_t attr;
//1. 線程屬性的初始化
rc = pthread_mutexattr_init(&attr);
if(rc != 0)
{
throw YR_ThreadMutex_Exception("[YR_ThreadRecMutex::YR_ThreadRecMutex] pthread_mutexattr_init error", rc);
}
//2. 設置線程鎖類型,PTHREAD_MUTEX_RECURSIVE爲嵌套鎖
rc = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
if(rc != 0)
{
throw YR_ThreadMutex_Exception("[YR_ThreadRecMutex::YR_ThreadRecMutex] pthread_mutexattr_settype error", rc);
}
//3. 初始化線程
rc = pthread_mutex_init(&_mutex, &attr);
if(rc != 0)
{
throw YR_ThreadMutex_Exception("[YR_ThreadRecMutex::YR_ThreadRecMutex] pthread_mutex_init error", rc);
}
//4. 銷燬線程屬性對象
rc = pthread_mutexattr_destroy(&attr);
if(rc != 0)
{
throw YR_ThreadMutex_Exception("[YR_ThreadRecMutex::YR_ThreadRecMutex] pthread_mutexattr_destroy error", rc);
}
}
YR_ThreadRecMutex::~YR_ThreadRecMutex()
{
while (_count)
{
unlock();
}
int rc = 0;
rc = pthread_mutex_destroy(&_mutex); //銷燬線程
if(rc != 0)
{
cerr << "[YR_ThreadRecMutex::~YR_ThreadRecMutex] pthread_mutex_destroy error:" << string(strerror(rc)) << endl;
}
}
加鎖
int YR_ThreadRecMutex::lock() const
{
int rc = pthread_mutex_lock(&_mutex);
if(rc != 0)
{
//嵌套鎖不用判斷EDEADLK
throw YR_ThreadMutex_Exception("[YR_ThreadRecMutex::lock] pthread_mutex_lock error",rc);
}
//只是計數加1,pthread_mutex_unlock避免鎖疊加
if(++_count > 1)
{
rc = pthread_mutex_unlock(&_mutex);
assert(rc == 0);
}
return rc;
}
解鎖
int YR_ThreadRecMutex::unlock() const
{
//當計數只有1的時候進行解鎖操作,大於1的情況只是計數減一即可
if(--_count == 0)
{
int rc = 0;
rc = pthread_mutex_unlock(&_mutex);
return rc;
}
return 0;
}
嘗試鎖
bool YR_ThreadRecMutex::tryLock() const
{
int rc = pthread_mutex_trylock(&_mutex);
if(rc != 0 )
{
if(rc != EBUSY)
{
throw YR_ThreadMutex_Exception("[YR_ThreadRecMutex::tryLock] pthread_mutex_trylock error", rc);
}
}
else if(++_count > 1)
{
rc = pthread_mutex_unlock(&_mutex);
if(rc != 0)
{
throw YR_ThreadMutex_Exception("[YR_ThreadRecMutex::tryLock] pthread_mutex_unlock error", rc);
}
}
return (rc == 0);
}
計數
int YR_ThreadRecMutex::count() const
{
int c = _count;
_count = 0;
return c;
}
void YR_ThreadRecMutex::count(int c) const
{
_count = c;
}
unlock()之後是否會解鎖
bool YR_ThreadRecMutex::willUnlock() const
{
return _count == 1;
}