zoukankan      html  css  js  c++  java
  • ACE_Recursive_Thread_Mutex 死锁bug

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

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

    1. int ACE_Recursive_Thread_Mutex::acquire()  
    2. {  
    3.     ACE_thread_t t_id = ACE_OS::thr_self();  
    4.     ACE_GUARD_RETURN(ACE_Thread_Mutex, guard, lock_, -1);  
    5.     if(nesting_level_ == 0){  
    6.         owner_id_ = t_id;  
    7.         nesting_level_ = 1;  
    8.     }  
    9.     else if(t_id == owner_id_)  
    10.          nesting_level_ ++;  
    11.     else{  
    12.          while( nesting_level_ > 0)  
    13.              lock_available_.wait();  
    14.           owner_id_ = t_id;  
    15.           nesting_level_ = 1;  
    16.     }  
    17.     return 0;  
    18. }  

    在申请递归互斥体的操作上,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_,代码如下

    1. int ACE_Recursive_Thread_Mutex::release()  
    2. {  
    3.     owner_id_ = 0;  
    4.       
    5.     ACE_GUARD_RETURN(ACE_Thread_Mutex, guard, lock_, -1);  
    6.       
    7.     nesting_level_ --;      
    8.     if(nesting_level_ == 0)  
    9.        lock_available_.signal();  
    10.       
    11.     return 0;  
    12. }  

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

    1. int ACE_Recursive_Thread_Mutex::acquire()  
    2. {  
    3.     ACE_thread_t t_id = ACE_OS::thr_self();  
    4.     ACE_GUARD_RETURN(ACE_Thread_Mutex, guard, lock_, -1);  
    5.     if(nesting_level_ == 0){  
    6.         owner_id_ = t_id;  
    7.         nesting_level_ = 1;  
    8.     }  
    9.     else if(t_id == owner_id_)  
    10.          nesting_level_ ++;  
    11.     else{  
    12.          while( nesting_level_ > 0)  
    13.          {  
    14.              guard.release();  
    15.              lock_available_.wait();  
    16.              guard.acquire();   
    17.          }   
    18.          owner_id_ = t_id;  
    19.          nesting_level_ = 1;  
    20.     }  
    21.     return 0;  
    22. }  


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

    补充:

    新版的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个 互斥体 申请 ,已经解决这个问题了

  • 相关阅读:
    北漂爱情[柒涩波]
    JavaScript基础知识五
    JavaScript基础知识四
    JavaScript基础知识三
    JavaScript基础知识二
    js内存泄漏
    CSS三列布局之左右宽度固定,中间元素自适应问题
    VScode 前端常用插件推荐
    将博客搬至CSDN
    python网络编程学习笔记(二)
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13318553.html
Copyright © 2011-2022 走看看