ACE学习(四)ACE_Recursive_Thread_Mutex与ACE_RW_Thread_Mutex

来源:互联网 发布:access vb编程入门 编辑:程序博客网 时间:2024/05/29 09:59

ACE_Recursive_Thread_Mutex与ACE_RW_Thread_Mutex


1.不同平台使用有差异性

/**
 * @class ACE_Thread_Mutex
 *
 * @brief ACE_Thread_Mutex wrapper (only valid for threads in the same
 * process).
 *
 * This implementation is optimized for locking threads that are
 * in the same process.  It maps to <CRITICAL_SECTION>s on NT
 * and <ACE_mutex_t> with <type> set to <USYNC_THREAD> on UNIX.
 * ACE_Thread_Mutex is recursive on some platforms (like
 * Win32). However, on most platforms (like Solaris) it is not
 * recursive.  To be totally safe and portable, developers
 * should use ACE_Recursive_Thread_Mutex when they need a
 * recursive mutex.
 */

ACE的ACE_Thread_Mutex互斥锁在windows平台上是可重入的,而在Linux平台上是不可重入的,原因上面也有说明Windows下是使用Critical Section实现的,而Critical Section在window下是可递归的。Linux下的pthread_mutex_t锁默认(USYNC_THREAD)是非递归的。可以显示的设置PTHREAD_MUTEX_RECURSIVE属性,将pthread_mutex_t设为递归锁。

 

 

 

2.锁最好不要复制

在ACE中ACE_Thread_Mutex也没有拷贝构造函数,即使有使用起来也会很不安全,一般都用锁的拷贝或者引用来传递。如果锁可以拷贝,那么可能出现两个线程同时拥有一个锁,同时对数据操作的情况,这个时候和没有加锁一样了。

 

3.读写锁必须使用得当

 


读写锁允许多个线程同时持有一个锁进行读取,但只有一个线程能够持有这个锁进行写入,可以带来效率的提高。特别是在受保护的多个线程常被多个线程读取,但不常被写入,或是只被很少几个线程写入。但是在大多数情况下读写锁都比互斥体要慢,因此,只在读取竞争大大超过写入竞争的时候使用它。

 

 

 

4.递归锁Demo

// thread_recursive_mutex.cpp#include "ace/Task.h"typedef ACE_Recursive_Thread_Mutex MUTEX;// will cause deadlock in linux, in win32 its ok//typedef ACE_Thread_Mutex MUTEX;class Logger{public:void log(void){ACE_GUARD(MUTEX, mon, m_metex);//in some caselockAgain();}void lockAgain(){// acquires the same mutex as log();ACE_GUARD(MUTEX, mon, m_metex);}private:MUTEX m_metex;};int ACE_TMAIN(int, ACE_TCHAR *[]){Logger log;log.log();return 0;};


 

 5.读写锁Demo

 

下面这个Demo模拟的是检测家庭中的设备是否在网络中,一般添加设备很少,而要经常检查,这种场合可以使用,在添加两个设备后,每隔1秒读取一次设备是否在网络中,开启读取线程3秒后移除一个设备,然后继续读取。

// thread_rw_mutex.cpp#include "ace/Task.h"#include <iostream>#include <list>#include <algorithm>#include <functional>using namespace std;class Device{public:Device(int id):deviceID(id){}int deviceID;};class isEqual{public:isEqual(int id):m_id(id){}bool operator() (Device *device){return device->deviceID == m_id;}private:int m_id;};class HADiscoverAgent{public:void addDevice(Device *device){ACE_WRITE_GUARD(ACE_RW_Thread_Mutex, mon, m_rwmutex);m_DeviceList.push_back(device);ACE_DEBUG((LM_DEBUG, ACE_TEXT("Device is add, the device id is: %d\n"), device->deviceID));}void removeDevice(Device *device){ACE_WRITE_GUARD(ACE_RW_Thread_Mutex, mon, m_rwmutex);m_DeviceList.remove(device);ACE_DEBUG((LM_DEBUG, ACE_TEXT("Device is remove, the device id is: %d\n"), device->deviceID));ACE_OS::sleep(5);}// check device is in net, return the device id or return -1int containsDevice(Device *device){ACE_READ_GUARD_RETURN(ACE_RW_Thread_Mutex, mon, m_rwmutex, -1);list<Device *>::iterator pos = find_if(m_DeviceList.begin(), m_DeviceList.end(), isEqual(1));int ret = -1;if (pos != m_DeviceList.end()){ret = (*pos)->deviceID;}return ret;}private:ACE_RW_Thread_Mutex m_rwmutex;list<Device*> m_DeviceList;};class myThread:public ACE_Task_Base{public:myThread(HADiscoverAgent *da, Device *device):m_da(da), m_device(device){}virtual int svc(){// check 10 times for (int i=0; i<10; i++){int tmp = m_da->containsDevice(m_device);if (tmp != -1){ACE_DEBUG((LM_DEBUG, ACE_TEXT("Device %d is in net!\n"), tmp));}else{ACE_DEBUG((LM_DEBUG, ACE_TEXT("Device %d is not in net!\n"), m_device->deviceID));}ACE_OS::sleep(1);}return 0;}private:HADiscoverAgent *m_da;Device *m_device;};int ACE_TMAIN(int, ACE_TCHAR *[]){Device d1(1);Device d2(2);HADiscoverAgent da;da.addDevice(&d1);da.addDevice(&d2);// start thread to read device ten times in 10smyThread mTh(&da, &d1);mTh.activate();// read the device info before remove deviceACE_OS::sleep(3);// remove device, now the write is use, da can read until write is overda.removeDevice(&d1);mTh.wait();return 0;};


 

 

原创粉丝点击