对于,线程锁来说,最可怕就是出现由于某种原因没有解锁从而造成线程死锁。C++的对象构造和析构给出了很好的办法,具体的实现不外乎先前《自行释放ACE_Message_Block》中所写的那样。这里所要说的是ACE已经作了的工作。
#define ACE_GUARD_ACTION(MUTEX, OBJ, LOCK, ACTION, REACTION) /
ACE_Guard< MUTEX > OBJ (LOCK); /
if (OBJ.locked () != 0) { ACTION; } /
else { REACTION; }
#define ACE_GUARD_REACTION(MUTEX, OBJ, LOCK, REACTION) /
ACE_GUARD_ACTION(MUTEX, OBJ, LOCK, ;, REACTION)
#define ACE_GUARD(MUTEX, OBJ, LOCK) /
ACE_GUARD_REACTION(MUTEX, OBJ, LOCK, return)
#define ACE_GUARD_RETURN(MUTEX, OBJ, LOCK, RETURN) /
ACE_GUARD_REACTION(MUTEX, OBJ, LOCK, return RETURN)
这是ACE定义的宏,用这些宏可以方便地节省很多代码量,虽然实际上代码就是一样的。Metex代表锁的种类,Obj代表ACE_Guard的对象,ACTION代表成功的动作,REACTION代表加锁失败的动作。
在ACE中存在读锁和写锁的区别,所以这些宏ACE_Guard也会派生出读锁和写锁。ACE_Guard存在显示的加锁和解锁,但在构造的时候会默认加锁。析构的时候会根据对象是否认为已经加锁,来进行解锁。当然还存在一些其他函数,但这并非是重点了。
写着这些是认为ACE_Guard是非常重要的。我并不认为很多人会产生加锁的不对称,然而没有知道异常什么时候会发生,所以就审慎一些为好。然而事务都是两面的,这容易产生加锁范围过大的情况,给死锁的形成埋下隐患,所以要适时显示解锁。加锁的原则就是范围越小越好。