andylin02 发表于 2013-1-15 02:52:57

ACE线程管理机制-并发控制(2)

ACE线程管理机制-并发控制(2)


与C一级的互斥体API相比较,Mutex包装为同步多线程控制提供了一种优雅的接口。但是,Mutex潜在地容易出错,因为程序员有可能忘记调用release方法(当然,C级的互斥体API更容易出错)。这可能由于程序员的疏忽或是C++异常的发生而发生,然而,其导致及其严重的后果--死锁。


因此,为改善应用的健壮性,ACE同步机制有效地利用C++类构造器和析构器的语义来确保Mutex锁被自动获取和释放。


ACE提供了一个称为Guard、Write_Guard和Read_Guard的类族,确保在进入和退出C++代码块时分别自动获取和释放锁。


Guard类是最基本的守卫机制,定义可以简化如下(实际定义比这相对要复杂而完善一点):
template <class LOCK>class Guard{public:    Guard (LOCK &l): lock_ (&l){ lock_.acquire (); }    ˜Guard (void) {    lock_.release (); }private:    LOCK lock_;}
Guard类的对象定义一"块"代码,在其上锁被自动获取,并在退出块时自动释放,即使是程序抛异常也能保证自动解锁。这种机制也能为Mutex、RW_Mutex和Semaphore同步封装工作。


对于读写锁,由于加锁接口不一样,ace也提供了相应的Read_Guard和Write_Guard类,Read_Guard和Write_Guard类有着与Guard类相同的接口。但是,它们的acquire方法分别对锁进行读和写。


缺省地, Guard类构造器将会阻塞程序,直到锁被获取。会有这样的情况,程序必须使用非阻塞的acquire调用(例如,防止死锁)。因此,可以传给ACE Guard的构造器第二个参数(请参看原始代码,而不是我这里的简化代码),指示它使用锁的try_acquire方法,而不是acquire。随后调用者可以使用Guard的locked方法来原子地测试实际上锁是否已被获取。


用Guard重写上一节的Thread1方法如下(注释了的部分是原有代码):
void* Thread1(void *arg) {    ACE_Guard<ACE_Thread_Mutex> guard(mutex);    //mutex.acquire();    ACE_OS::sleep(3);    cout<<endl<<"hello thread1"<<endl;    //mutex.release();    return NULL; } 
相比较而言,使用Guard更加简洁,并且会自动解锁,免除了一部分后顾之忧。


注意:


Guard只能帮你自动加解锁,并不能解决死锁问题,特别是对于那些非递归的互斥体来说使用Guard尤其要注意防止死锁。
Guard是在Guard变量析构时解锁,如果在同一函数中两次对同一互斥体变量使用Guard要注意其对象生命周期,否则容易造成死锁。
页: [1]
查看完整版本: ACE线程管理机制-并发控制(2)