Linux多線程C++工具庫:liblmp_tool -- RAII手法封裝互斥鎖MutexLock

 

Linux多線程編程工具庫liblmp_tool   github: https://github.com/Dwyane05/liblmp_tool

 

互斥鎖(mutex)恐怕是使用得最多的同步原語,粗略地說,它保護了臨界區,任何一個時刻最多只能有一個線程在此mutex劃出的臨界區內活動。單獨使用mutex時,我們主要爲了保護共享數據。

個人的原則是:
·用RAII手法封裝mutex的創建、銷燬、加鎖、解鎖這四個操作。用RAII封裝這幾個操作是通行的做法,這幾乎是C++的標準實踐。

·只用非遞歸的mutex(即不可重入的mutex)。
·不手工調用lock()和unlock()函數,一切交給棧上的Guard對象的構造和析構函數負責。Guard對象的生命期正好等於臨界區(分析對象在什麼時候析構是C++程序員的基本功)。

·在每次構造Guard對象的時候,思考一路上(調用棧上)已經持有的鎖,防止因加鎖順序不同而導致死鎖(deadlock)。

次要原則有:
·不使用跨進程的mutex,進程間通信只用TCP sockets。
·加鎖、解鎖在同一個線程,線程a不能去unlock線程b已經鎖住的mutex(RAII自動保證)。
·別忘了解鎖(RAII自動保證)。
·不重複解鎖(RAII自動保證)。
·必要的時候可以考慮用PTHREAD_MUTEX_ERRORCHECK來排錯。

 

相關類的實現:


#include "Thread.h"

#include “noncopyable.h”
#include <assert.h>
#include <pthread.h>
#include <stdio.h>

namespace lmp_tool
{

class MutexLock : noncopyable
{
 public:
  MutexLock()
    : holder_(0)
  {
    pthread_mutex_init(&mutex_, NULL);
  }

  ~MutexLock()
  {
    assert(holder_ == 0);
    pthread_mutex_destroy(&mutex_);
  }

  bool isLockedByThisThread()
  {
    return holder_ == CurrentThread::tid();
  }

  void assertLocked()
  {
    assert(isLockedByThisThread());
  }

  // internal usage

  void lock()
  {
    pthread_mutex_lock(&mutex_);
    holder_ = CurrentThread::tid();
  }

  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 : noncopyable
{
 public:
  explicit MutexLockGuard(MutexLock& mutex) : mutex_(mutex)
  {
    mutex_.lock();
    printf( "mutex locked\n");
  }

  ~MutexLockGuard()
  {
    mutex_.unlock();
    printf( "mutex unlocked\n");
  }

 private:

  MutexLock& mutex_;
};

}

// Prevent misuse like:
// MutexLockGuard(mutex_);
// A tempory object doesn't hold the lock for long!
#define MutexLockGuard(x) error "Missing guard object name"

 

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