C++ 封装互斥对象

  多线程程序中为了防止线程并发造成的竞态,需要经常使用到Mutex进行数据保护。posix提供了phtread_mutex_t进行互斥保护数据。Mutex的使用需要初始化和释放对应(phtread_mutex_init() 和 phtread_mutex_destroy() 对应),上锁和解锁对应(phtread_mutex_lock 和 pthread_mutex_unlock对应)。lock和unlock的过程是设计逻辑的一部分一般都程序员都能正确的进行加锁和解锁对应,但是要防止lock之后程序出现异常或者提前return而没有unlock。初始化mutex之后不释放也会造成资源泄漏,也是很容易遗漏的地方。在实际开发中一般都需要自己封装一下Mutex。

class MutexLock
{
 public:
  MutexLock() : holder_(0)
  {
    int ret = pthread_mutex_init(&mutex_, NULL);
    assert(ret == 0);
  }

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

  bool isLockedByThisThread() const
  {
    return holder_ == static_cast<pid_t>(::syscall(SYS_gettid));
  }

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

  void lock()
  {
    pthread_mutex_lock(&mutex_);
    assignHolder();
  }

  void unlock()
  {
    unassignHolder();
    pthread_mutex_unlock(&mutex_);
  }

  pthread_mutex_t* getPthreadMutex()
  {
    return &mutex_;
  }

 private:

  MutexLock(const MutexLock &);
  MutexLock &operator=(const MutexLock &);

  void unassignHolder()
  {
    holder_ = 0;
  }

  void assignHolder()
  {
    holder_ = static_cast<pid_t>(::syscall(SYS_gettid));
  }

  pthread_mutex_t mutex_;
  pid_t holder_;
};

class MutexLockGuard
{
 public:
  explicit MutexLockGuard(MutexLock& mutex)
    : mutex_(mutex)
  {
    mutex_.lock();
  }

  ~MutexLockGuard()
  {
    mutex_.unlock();
  }

 private:
  MutexLockGuard(const MutexLockGuard &);
  MutexLockGuard &operator=(const MutexLockGuard &);

  MutexLock& mutex_;
};

  为了提高MutextLock的易用性,增加了一个MutexLockGuard 类来封装MutextLock,实际使用的时候直接使用MutexLockGuard,这样就能防止忘记释放Mutex的情况出现(MutexLockGuard 超出作用域(一般是一个栈上变量)就会自动释放,调用析构函数,destroy掉mutex)。

  注:其实在C++11 线程库中已经有lock guard可以直接使用了(std::lock_guard ,只需要include<mutex>),不需要自己再写一遍,对于没有迁移到C++11上的项目可以使用自己封装的Mutex来提高易用性。

时间: 2024-10-23 19:47:15

C++ 封装互斥对象的相关文章

Windows 互斥对象在线程同步上的运用

互斥对象在线程同步时的使用 1 多线程在资源共享的时候出现的问题 在程序中如果不同线程对同一个对象进行操作的话就有可能出现因为线程切换而导致的问题.例如下面的程序 #include <stdio.h> #include <WinSock2.h> #include <iostream> using namespace std; #pragma comment(lib,"ws2_32.lib") DWORD WINAPIfun1Proc(LPVOID l

C#多线程学习(六) 互斥对象

C#多线程学习(六) 互斥对象 如何控制好多个线程相互之间的联系,不产生冲突和重复,这需要用到互斥对象,即:System.Threading 命名空间中的 Mutex 类. 我们可以把Mutex看作一个出租车,乘客看作线程.乘客首先等车,然后上车,最后下车.当一个乘客在车上时,其他乘客就只有等他下车以后才可以上车.而线程与Mutex对象的关系也正是如此,线程使用Mutex.WaitOne()方法等待Mutex对象被释放,如果它等待的Mutex对象被释放了,它就自动拥有这个对象,直到它调用Mute

【转】临界区、互斥对象

1.什么是临界区? 答:每个进程中访问临界资源的那段程序称为临界区(临界资源是一次仅允许一个进程使用的共享资源).每次只准许一个进程进入临界区,进入后不允许其他进程进入. 2.进程进入临界区的调度原则是: ①如果有若干进程要求进入空闲的临界区,一次仅允许一个进程进入. ②任何时候,处于临界区内的进程不可 多于一个.如已有进程进入自己的临界区,则其它所有试图进入临界区的进程必须等待. ③进入临界区的进程要在有限时间内退出,以便其它进程能及时进入自己的 临界区. ④如果进程不能进入自己的临界区,则应

多线程同步之互斥对象

多线程同步之互斥对象 作者:vpoet mail:[email protected] 在http://blog.csdn.net/u013018721/article/details/46637215一文中介绍了使用临界区 对卖票问题进行线程间同步,本文将在上文的基础上,使用互斥对象对线程进行同步. 首先看看windows API 该函数创建一个命名或者不命名的互斥对象 lpMutexAttributes [in] Pointer to a SECURITY_ATTRIBUTES structu

【转】互斥对象锁和临界区锁性能比较

原作者:chexlong 原文地址:http://blog.csdn.net/chexlong/article/details/7060425 在Win32平台上进行多线程编程,常会用到锁.下边用C++实现了互斥对象(Mutex)锁和临界区(CRITICAL_SECTION)锁,以加深理解和今后方便使用.代码已在VS2005环境下编译测试通过. Lock.h [cpp] view plaincopy #ifndef _Lock_H #define _Lock_H #include <window

xml的信息封装到对象

1.xml文件 <?xml version="1.0" encoding="utf-8"?> <?xml-stylesheet type="text/css" href="03.contact.css"?> <contactList> <contact id="001"> <name>张三</name> <age>20<

windows下多线程同步(利用事件对象,互斥对象,关键代码段)实现

一:利用事件实现线程同步 1.createthread函数的用法 hThread = CreateThread(&security_attributes, dwStackSize, ThreadProc,pParam, dwFlags, &idThread) ; HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes, DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAdd

Delphi多线程编程(10)--多线程同步之Mutex(互斥对象)

原理分析: 互斥对象是系统内核对象,各个线程都可以拥有它,谁拥有它谁就可以执行 执行完毕,用ReleaseMutex 函数释放拥有权,以让其他等待的线程可以使用 其他线程可以使用 WaitForSingleObject函数排队等待(等待也可以理解为排队申请) 使用过程 var hMutex: THandle; {应该先声明一个全局的互斥句柄} CreateMutex {建立互斥对象} WaitForSingleObject {用等待函数排队等候} ReleaseMutex {释放拥有权} Clo

ALIAS_TO_ENTITY_MAP 封装成对象

ALIAS_TO_ENTITY_MAP   封装成对象 protected List<?> executeSQLMapQuery(String sql, Object param, int start,            int limit) {        Query query = null;        query = this.getSession().createSQLQuery(sql)                .setResultTransformer(Transf