您的位置:首页 > 其它

常用ACE锁的类型分析及使用规则

2010-05-15 22:34 375 查看
 

NJZhuJinhua@csdn May.15, 2010

mail:jinhua1982@gmail.com
http://blog.csdn.net/njzhujinhua
转载请注明出处。

朱金华

 

 

近期对ACE锁进行分析,进一步整理如下。

用到的锁的类型

1.1    ACE_Mutex

封装互斥机制(根据平台,可以是mutex_t、pthread_mutex_t等等)的包装类,用于提供简单而有效的机制来使对共享资源的访问序列化。它与二元信号量(binary semaphore)的功能相类似。可被用于线程和进程间的互斥。

1.2    ACE_RW_Mutex

封装读者/作者锁的包装类。它们是分别为读和写进行获取的锁,在没有作者在写的时候,多个读者可以同时进行读取。可用于替换ACE_Mutex。此锁用于大部分读少部分写的情况下优势明显。

内部实现含有acquire(), acquire_read(), acquire_write()等。

acquire_read()获取读锁,如果一个写锁已经锁定则阻塞;acquire_write()获取一个写锁,当任何读锁或写锁被锁定时此函数阻塞。Acquire()只是为了接口统一,其实现等价于acquire_write()。此段分析后续有用。

目前主要使用于配置部分的代码。

1.3    ACE_Thread_Mutex

可用于替换ACE_Mutex,专用于线程同步。

内部实现含有acquire(), acquire_read(), acquire_write()等。

acquire()用于获取锁;acquire_read()和acquire_write()则只是为了接口统一,其实现等价于acquire()。此段分析后续有用。

1.4    ACE_Recursive_Thread_Mutex

线程递归互斥锁,使用该锁,能够锁住两个线程访问同一个资源,同时对同一个线程,可以递归使用,而不至于出现死锁。要求释放次数必须与获取次数一致。目前主要应用于会话管理相关代码。

1.5    ACE_RW_Thread_Mutex

ACE读写线程锁。可用于替换ACE_RW_Mutex,专用于线程同步。

建议的ACE锁的使用规则

总则:对于在同一个函数内获取锁并随后释放的情形,务必使用ACE_Guard/ ACE_Read_Guard/ ACE_Write_Guard来进行守护。

2.1    ACE_Mutex

这个就不要使用了。

2.2    ACE_RW_Mutex

对于大量读取偶尔写入的建议用ACE_RW_Mutex锁。使用ACE_Read_Guard(实际为ACE_RW_Mutex的acquire_read())时允许多个线程同时读取。

2.3    ACE_Thread_Mutex

专用于线程间的保护,其实我们主要就是防范线程间修改这种情形。

当各个线程不能同时访问同一段数据区,如不能同时处理同一个业务对象,不能同时处理一个session等情形,甚至引用计数需要每个线程分清先后,顺序进行时也可以用ACE_Thread_Mutex。(当然,对于引用计数或int,unsigned int的原子操作我们有更好的AtomInt,其定义如下:

typedef ACE_Atomic_Op<ACE_Thread_Mutex, int> AtomInt;)

2.4    ACE_Recursive_Thread_Mutex

对于函数A需要对数据区加锁后执行函数B,函数B同样要获取锁时,即同一线程允许多次获取锁,而其他线程则继续阻塞时,务必使用ACE_Recursive_Thread_Mutex,不然将死锁。

但不可把适用于ACE_Thread_Mutex的地方都改成递归锁,效率上ACE_Thread_Mutex比递归锁要高。

2.5    ACE_RW_Thread_Mutex

继承自ACE_RW_Mutex。多了接口tryacquire_write_upgrade而已。即如果一个线程获取了读锁,同时没有其他线程拥有读锁时,可以升级为写锁。成功返回0,否则返回-1并设置errno为EBUSY。

当读操作远大于对数据区的写操作时,并且在进性读取后还有可能某条件下写时使用这个:

 

//先获取读锁,检查全局变量

ACE_Read_Guard<ACE_RW_Thread_Mutex>  guard(CurrentSalaryacerwthreadmutex);

If(加薪了)

{

    //偶尔需要更新

    If(-1 != CurrentSalaryacerwthreadmutex.tryacquire_write_upgrade())

    {

        G_CurrentSalary=$$$$$;

    }

}      

     
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息