线程锁的封装
线程锁的基本操作:
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;
}