一、互斥锁封装:Mutex.h
github地址:https://github.com/chenshuo/muduo/blob/master/muduo/base/Mutex.h
1.1 MutexLock类
互斥量是线程同步常用的变量,但在实际中一般都是使用封装的函数,这样便于操作。
MutexLock封装临界区(critical section),这是一个简单的资源类,用RAII手法封装互斥器的创建与销毁。
void lock()
{
MCHECK(pthread_mutex_lock(&mutex_));
assignHolder();
}
检查返回值的意义在于防止ENOMEM 之类的资源不足情况,这一般只可能在负载很重的产品程序中出现。一旦出现这种错误,程序必须清理现场并主动退出,否则会莫名其妙的崩溃,给事后调查造成困难。可用non-debug的assert,或借鉴google-glog的CHECK()宏
定义的MCHECK宏
#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)
__THROW __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
// Prevent misuse like:
// MutexLockGuard(mutex_);
// A tempory object doesn't hold the lock for long!
#define MutexLockGuard(x) error "Missing guard object name"
void doit()
{
MutexLockGuard(mutex); //漏写变量名,产生一个临时对象又马上销毁了,结果没锁住临界区
//正确写法是 MutexLockGuard lock(mutex);
//临界区
}
void wait()
{
MutexLock::UnassignGuard ug(mutex_);//这里先给mutex_的holder_置零。在等其析构时会给holder_赋值
MCHECK(pthread_cond_wait(&pcond_, mutex_.getPthreadMutex()));//给mutex_解锁
}
// returns true if time out, false otherwise.
bool muduo::Condition::waitForSeconds(double seconds)
{
struct timespec abstime;
// FIXME: use CLOCK_MONOTONIC or CLOCK_MONOTONIC_RAW to prevent time rewind.
clock_gettime(CLOCK_REALTIME, &abstime);
const int64_t kNanoSecondsPerSecond = 1e9;
int64_t nanoseconds = static_cast(seconds * kNanoSecondsPerSecond);
abstime.tv_sec += static_cast((abstime.tv_nsec + nanoseconds) / kNanoSecondsPerSecond);
abstime.tv_nsec = static_cast((abstime.tv_nsec + nanoseconds) % kNanoSecondsPerSecond);
MutexLock::UnassignGuard ug(mutex_);
return ETIMEDOUT == pthread_cond_timedwait(&pcond_, mutex_.getPthreadMutex(), &abstime);
}
如果一个class要包含MutexLock和
Condition,请注意它们的声明顺序和初始化顺序,mutex_应该先于condition_构造,并作为后者的构造参数。
#include
#include
#include
#include
#include
using namespace muduo;
CountDownLatch latch_(1);
void Function()
{
latch_.wait();//wait for latch_ countDown
printf("Thread ID=%d, Name=%s\n", CurrentThread::tid(), CurrentThread::name());
}
int main()
{
Thread t1(boost::bind(Function), "Thread 1");
Thread t2(boost::bind(Function), "Thread 2");
t1.start();
t2.start();
printf("main thread running, before countDown\n");
latch_.countDown();
sleep(3);//wait for thread t1, t2
printf("main thread running, after countDown\n");
t1.join();
t2.join();
return 0;
}
运行结果: