(14)muduo_base庫源碼分析:MutexLock類,MutexLockGuard類,Condition類

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章