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