ACE_Recursive_Thread_Mutex 死锁bug


ACE_Recursive_Thread_Mutex 的设计目的是为了避免代码中某个线程自己递归对互斥体进行申请而变成死锁的情况

但通过对其介绍文章的阅读 (参考<C++网络编程卷1> 10.6 ACE条件变量类) 发现实现上也可能会因为线程间的竞争ACE_Thread_Mutex 和 ACE_Condition_Thread_Mutex 2个不同资源时形成互锁,代码如下

int ACE_Recursive_Thread_Mutex::acquire()
{
    ACE_thread_t t_id = ACE_OS::thr_self();
    ACE_GUARD_RETURN(ACE_Thread_Mutex, guard, lock_, -1);
    if(nesting_level_ == 0){
        owner_id_ = t_id;
        nesting_level_ = 1;
    }
    else if(t_id == owner_id_)
         nesting_level_ ++;
    else{
         while( nesting_level_ > 0)
             lock_available_.wait();
          owner_id_ = t_id;
          nesting_level_ = 1;
    }
    return 0;
}

在申请递归互斥体的操作上,acquire 先确定调用线程的id ,然后通过scoped locking 技术得到 ACE_Thread_Mutex lock_ 从而得以串行化访问nesting_level_和owner_id_,

ACE_Condition_Thread_Mutex    lock_available_  条件变量实际为真正用来挂起 非所有者线程 ,这些挂起线程需要等待嵌套计数 nesting_level_ 被占用线程降至0且互斥体被释放

出问题的代码在于lock_available_.wai()t前已经通过Ace_Guard 将 lock_ 给占用了, 而其等待的lock_available_.signal() 却需要先取得lock_,代码如下

int ACE_Recursive_Thread_Mutex::release()
{
    owner_id_ = 0;
    
    ACE_GUARD_RETURN(ACE_Thread_Mutex, guard, lock_, -1);
    
    nesting_level_ --;    
    if(nesting_level_ == 0)
       lock_available_.signal();
    
    return 0;
}

理想的修改方式是在 lock_available_.wait() 一句前先释放自己占用的 资源 guard.release() 然后再lock_available_.wait()  返回后 再次 guard.acquire() 下。像这样

int ACE_Recursive_Thread_Mutex::acquire()
{
    ACE_thread_t t_id = ACE_OS::thr_self();
    ACE_GUARD_RETURN(ACE_Thread_Mutex, guard, lock_, -1);
    if(nesting_level_ == 0){
        owner_id_ = t_id;
        nesting_level_ = 1;
    }
    else if(t_id == owner_id_)
         nesting_level_ ++;
    else{
         while( nesting_level_ > 0)
         {
             guard.release();
             lock_available_.wait();
             guard.acquire(); 
         } 
         owner_id_ = t_id;
         nesting_level_ = 1;
    }
    return 0;
}


---------------------------------------------------------------------------------------------------------------

补充:

新版的ACE_Condition_Thread_Mutex 实现放在了 ACE_OS::recuersive_mutex_cond_relock ACE_OS::recuersive_mutex_cond_unlock 上,

 用 ACE_OS::cond_wait((ACE_thread_mutex_t *) &m->lock_available_,(ACE_cond_t*) &m->nesting_mutex_); 同时对2个 互斥体 申请 ,已经解决这个问题了


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值