mutex
初始化与销毁
#include <pthread.h>
int pthread_mutex_destroy(pthread_mutex_t *mutex);
int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_init
函数对 Mutex 做初始化,参数attr
设定Mutex的属性,如果attr
为NULL
则表示缺省属性。
pthread_mutex_init
函数初始化的Mutex可以用pthread_mutex_destroy
销毁。
- 如果 Mutex 变量是静态分配的(全局变量或
static
变量),也可以用宏定义PTHREAD_MUTEX_INITIALIZER
来初始化,相当于用pthread_mutex_init
初始化并且attr
参数为NULL
。
- 成功返回0,失败返回错误号。
加锁解锁
#include <pthread.h>
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
- 一个线程可以调用
pthread_mutex_lock
获得Mutex,如果这时另一个线程已经调用 pthread_mutex_lock
获得了该Mutex,则当前线程需要挂起等待,直到另一个线程调用 pthread_mutex_unlock
释放Mutex,当前线程被唤醒,才能获得该Mutex并继续执行。
- 如果一个线程既想获得锁,又不想挂起等待,可以调用
pthread_mutex_trylock
,如果Mutex已经被另一个线程获得,这个函数会失败返回EBUSY,而不会使线程挂起等待。
- 成功返回0,失败返回错误号。
源码
#pragma once
#include <pthread.h>
#include <assert.h>
#include "NonCopyable.h"
#include "CurrentThread.h"
namespace muduo
{
//@ 检查返回值的宏
#ifdef CHECK_PTHREAD_RETURN_VALUE
#ifdef NDEBUG
__BEGIN_DECLS
extern void __assert_perror_fail (int errnum,
const char *file,
unsigned int line,
const char *function)
noexcept __attribute__ ((__noreturn__));
__END_DECLS
#endif
#define MCHECK(ret) ({ __typeof__ (ret) errnum = (ret);
if (__builtin_expect(errnum != 0, 0))
__assert_perror_fail (errnum, __FILE__, __LINE__, __func__);})
#else // CHECK_PTHREAD_RETURN_VALUE
#define MCHECK(ret) ({ __typeof__ (ret) errnum = (ret);
assert(errnum == 0); (void) errnum;})
#endif // CHECK_PTHREAD_RETURN_VALUE
class MutexLock : public NonCopyable
{
public:
MutexLock() : holder_(0)
{
MCHECK(pthread_mutex_init(&mutex_, nullptr));
}
~MutexLock()
{
assert(holder_ == 0); //@ 保证锁不被持有
MCHECK(pthread_mutex_destroy(&mutex_));
}
bool is_locked_by_this_thread() const
{
return holder_ == CurrentThread::tid();
}
void assert_locked() const
{
assert(is_locked_by_this_thread());
}
void lock()
{
MCHECK(pthread_mutex_lock(&mutex_));
assign_holder();
}
void unlock()
{
unassign_holder();
MCHECK(pthread_mutex_unlock(&mutex_));
}
pthread_mutex_t *get_mutex() //@ no const
{
return &mutex_;
}
private:
void assign_holder()
{
holder_ = CurrentThread::tid();
}
void unassign_holder()
{
holder_ = 0;
}
private:
friend class Condition; //@ Condition 需要使用到 UnassignGuard
class UnassignGuard : NonCopyable
{
public:
explicit UnassignGuard(MutexLock &owner) : owner_(owner)
{
owner_.unassign_holder();
}
~UnassignGuard()
{
owner_.assign_holder();
}
private:
MutexLock &owner_; //@ 存放引用
};
private:
pthread_mutex_t mutex_;
pid_t holder_;
};
//@ RAII 格式 MutexLock 使用
class MutexLockGuard : public NonCopyable
{
public:
explicit MutexLockGuard(MutexLock &mutex) : mutex_(mutex)
{
mutex_.lock();
}
~MutexLockGuard()
{
mutex_.unlock();
}
private:
MutexLock &mutex_;
};
//@ 避免构造一个临时的对象,例如 MutexLockGuard(mutex),临时对象不能一直持有锁
#define MutexLockGuard(x) error "Missing guard object name"
}