1.MutexLock类图,MutexLockGuard类图
-
MutexLock类图
-
MutexLockGuard类图,此类更加常用,使用RAII技法封装
-
MutexLock类与MutexLockGuard类的lock方法和unlock方法说明
void f()
{
mutex.lock()
...
if(条件)
{
return;//这里直接return,如果忘记umutex.unlock,会造成死锁
}
mutex.unlock;
}
void f()
{
MutexLockGuard lock(mutex);//在构造函数中加锁了
...
if(条件)
{
return;//这里直接return,那么lock对象的生命周期就结束了,自动调用析构函数解锁
}
}//这里返回,和上面的return解释一样
- 类之间的关系:3个
(1)关联关系
MutexLockGuard类使用了mutex类中的lock和unlock方法
(2)聚合关系
整体与局部的关系
(3)组合关系
整体与局部的关系,以及还负责对对象的销毁,就是组合关系
2.Mutex.h分析
- 位置:14\jmuduo\muduo\base\Mutex.h
// Use of this source code is governed by a BSD-style license
// that can be found in the License file.
//
// Author: Shuo Chen (chenshuo at chenshuo dot com)
#ifndef MUDUO_BASE_MUTEX_H
#define MUDUO_BASE_MUTEX_H
#include <muduo/base/CurrentThread.h>
#include <boost/noncopyable.hpp>
#include <assert.h>
#include <pthread.h>
namespace muduo
{
//MutexLock类继承至noncopyable,表示不可以拷贝的
class MutexLock : boost::noncopyable
{
public:
MutexLock()
: holder_(0)//holder_=0表示这个锁没有被任何一个线程使用
{
int ret = pthread_mutex_init(&mutex_, NULL);
assert(ret == 0); (void) ret;
}
~MutexLock()
{
assert(holder_ == 0);//断言这个锁没有被任何一个线程使用,才会去销毁这个锁
int ret = pthread_mutex_destroy(&mutex_);
assert(ret == 0); (void) ret;
}
bool isLockedByThisThread()
{
return holder_ == CurrentThread::tid();
}
//断言当前线程是否有锁
void assertLocked()
{
assert(isLockedByThisThread());
}
// internal usage
void lock()
{
pthread_mutex_lock(&mutex_);
holder_ = CurrentThread::tid();//将当前线程的tid保存至holder_
}
void unlock()
{
holder_ = 0;
pthread_mutex_unlock(&mutex_);
}
pthread_mutex_t* getPthreadMutex() /* non-const */
{
return &mutex_;
}
private:
pthread_mutex_t mutex_;
pid_t holder_;
};
class MutexLockGuard : boost::noncopyable
{
public:
explicit MutexLockGuard(MutexLock& mutex)
: mutex_(mutex)
{
mutex_.lock();//构造函数中调用lock
}
~MutexLockGuard()
{
mutex_.unlock();//析构函数中调用unlock
}
private:
MutexLock& mutex_;//MutexLockGuard对象生命期结束的时候,mutex_对象的生命期未结束
};
}
// Prevent misuse like:
// MutexLockGuard(mutex_);//不运行构造一个匿名的mutex对象,要不然会报错
// A tempory object doesn't hold the lock for long!
#define MutexLockGuard(x) error "Missing guard object name"
#endif // MUDUO_BASE_MUTEX_H
3.Mutex_test.cc分析
- 位置:14\jmuduo\muduo\base\tests\Mutex_test.cc
//#include <muduo/base/CountDownLatch.h>//多余不需要
#include <muduo/base/Mutex.h>
#include <muduo/base/Thread.h>
#include <muduo/base/Timestamp.h>
#include <boost/bind.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
#include <vector>
#include <stdio.h>
using namespace muduo;
using namespace std;
MutexLock g_mutex;
vector<int> g_vec;
const int kCount = 10*1000*1000;
void threadFunc()
{
for (int i = 0; i < kCount; ++i)
{
MutexLockGuard lock(g_mutex);//MutexLockGuard在构造函数中lock,在析构函数中unlock
g_vec.push_back(i);
}
}
int main()
{
const int kMaxThreads = 8;
g_vec.reserve(kMaxThreads * kCount);//预留8千万个整数=3亿bit,相当于300M左右的内存
//没有锁的测试
Timestamp start(Timestamp::now());//登记时间戳
for (int i = 0; i < kCount; ++i)
{
g_vec.push_back(i);
}
printf("single thread without lock %f\n", timeDifference(Timestamp::now(), start));//插入1千万个整数,看需要多少时间
//有锁的测试
//下面的这个是主线程
start = Timestamp::now();
threadFunc();
printf("single thread with lock %f\n", timeDifference(Timestamp::now(), start));
//下面的是创建子线程
for (int nthreads = 1; nthreads < kMaxThreads; ++nthreads)
{
boost::ptr_vector<Thread> threads;//释放时,能够销毁存放在vector的对象
g_vec.clear();
start = Timestamp::now();
//只有1个线程时,依次类推
for (int i = 0; i < nthreads; ++i)
{
threads.push_back(new Thread(&threadFunc));
threads.back().start();
}
//等待该线程结束。以此类推
for (int i = 0; i < nthreads; ++i)
{
threads[i].join();
}
printf("%d thread(s) with lock %f\n", nthreads, timeDifference(Timestamp::now(), start));
}
}
4.测试
- 需要修改内容:14\jmuduo\muduo\base\tests\CMakeLists.txt
。。。。
##新增
add_executable(mutex_test Mutex_test.cc)
target_link_libraries(mutex_test muduo_base)
##新增
。。。。。
-执行结果:
19:54