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

来源:互联网 发布:iphone最大的软件 编辑:程序博客网 时间:2024/05/22 12:17

 

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=$$$$$;
    }
}      
     

原创粉丝点击