代码之家  ›  专栏  ›  技术社区  ›  kevin h

std::recursive_mutex是否会导致死锁?

  •  1
  • kevin h  · 技术社区  · 1 年前

    我知道如果我锁定 std::mutex 在一个线程中出现两次,将导致死锁。

    所以,我在全球范围内取代了 std::互斥 具有 std::recursive_mutex .

    仅使用 std::recursive_mutex 意思是我永远不会遇到僵局?

    这有什么潜在的问题吗(除了速度稍微慢一点)?

    3 回复  |  直到 1 年前
        1
  •  2
  •   wohlstad    1 年前

    recursive_mutex 仅解决了当潜在死锁由1个需要访问1个受保护资源的线程引起时的问题。

    您仍然可以使用 递归_分钟 , 如果涉及多个资源 .

    考虑以下场景,其中涉及2个线程,它们需要独占访问2个资源(每个资源由互斥对象保护):

    1. ThreadA锁定RecursiveMutexA以获得对ResourceA的访问权限。
    2. ThreadB锁定RecursiveMutexB以获得对ResourceB的访问权限。
    3. ThreadA试图锁定RecursiveMutexB以获得对ResourceB的访问权限,并且 死锁 .
    4. ThreadB试图锁定RecursiveMutexA以获得对ResourceA的访问权限,并且 死锁 .

    这种情况的解决方案是,所有线程都必须锁定互斥对象 按相同顺序 .

        2
  •  2
  •   Ben A.    1 年前

    不同的命令或条件可能是你的敌人。考虑以下内容(我使用 namespace std 清理,尽管这通常不是最佳实践):

    #include <iostream>
    #include <thread>
    #include <mutex>
    
    using namespace std;
    recursive_mutex firstOne, secondOne;
    
    void threadingOne() {
        lock_guard<recursive_mutex> lock1(firstOne);
    
        //pretend stuff happens
        this_thread::sleep_for(chrono::milliseconds(100));
    
        lock_guard<recursive_mutex> lock2(secondOne);
    }
    
    void threadingTwo() {
        lock_guard<recursive_mutex> lock2(secondOne);
    
        //this is stuff happening
        this_thread::sleep_for(chrono::milliseconds(100));
    
        lock_guard<recursive_mutex> lock1(firstOne);
    }
    
    int main() {
        thread threadOne(threadingOne);
        thread threadTwo(threadingTwo);
        threadOne.join();
        threadTwo.join();
    
        cout << "This is not something you will see ever\n";
        return 0;
    }
    
    
        3
  •  1
  •   Sai Shiva    1 年前

    用std::recursive_mutex替换std::mutex有助于避免线程锁定自身导致的死锁。 这不是一个有保证的解决方案。如果锁定顺序或外部资源依赖关系错误,仍然可能发生死锁。 只有在递归锁定真正需要时才使用std::recursive_mutex。考虑其他替代方案。