Std::Lock 避免了死锁,但程序卡住了

问题描述 投票:0回答:2

所有, 参考std::lock中的问题仍然导致死锁

我仍然无法弄清楚下面的代码有什么问题。有人可以解释一下这个问题以及如何解决这个问题吗?为什么会挂?请帮忙。

#include <iostream>
#include <mutex>
#include <thread>
using namespace std;

std::mutex m1;
std::mutex m2;

void func1()
{
    std::unique_lock<std::mutex> lock1(m1, std::defer_lock);
    printf("func1 lock m1\n");
    std::this_thread::sleep_for(std::chrono::seconds(1));
    std::unique_lock<std::mutex> lock2(m2, std::defer_lock);
    printf("func1 lock m2\n");
    std::lock(m1, m2);
    printf("func1 std lock\n");

}

void func2()
{
    std::unique_lock<std::mutex> lock1(m2, std::defer_lock);
    printf("func2 lock m2\n");
    std::this_thread::sleep_for(std::chrono::seconds(1));
    std::unique_lock<std::mutex> lock2(m1, std::defer_lock);
    printf("func2 lock m1\n");
    std::lock(m1, m2);
    printf("func2 std lock\n");
}



int main(int argc,char* argv[])
{
    std::thread th1(func1);
    std::thread th2(func2);
    th1.join();
    th2.join();
    return 0;
}

看到的输出: func1 锁 m1
func2锁m2
func1 锁 m2
func1 标准锁
func2锁m1
-----挂在这里。

为什么即使 func1 已经释放了两个互斥锁,func2 仍不继续?

c++ multithreading c++11 mutex thread-synchronization
2个回答
12
投票

而不是:

std::lock(m1, m2);

用途:

std::lock(lock1, lock2);

更多详细信息(包括示例)可以在

std::lock
的参考页面上找到。

为什么你的代码挂起?

当调用

std::lock(m1, m2)
时,两个互斥体直接被锁定。
std::unique_lock
lock1
lock2
)都没有意识到这一点,因此它们无法解锁互斥锁。

因此,当

func1
结束时,两个互斥体仍然被锁定,并且
func2
无法继续越过
std::lock(m1, m2)
线。

为什么固定代码有效?

当您调用

std::lock(lock1, lock2)
时,
std::unique_lock
lock1
lock2
)知道这一点 - 他们现在拥有锁,并负责解锁它们(当它们超出范围时会发生这种情况)。

因此,当

func1
结束时,两个互斥锁都被解锁,并且
func2
can 继续越过
std::lock(lock1, lock2)
行。一切都很好。


0
投票

Unique_lock 无法解锁它们,因为你提到这些锁尚未被采用。

std::unique_lock<std::mutex> lock1(m1, std::defer_lock);
std::unique_lock<std::mutex> lock2(m2, std::defer_lock);

所以独特的锁无法解锁。

解决方案

            void func1()
            {
                std::unique_lock<std::mutex> lock1(m1, std::defer_lock);
                printf("func1 lock m1\n");
                std::this_thread::sleep_for(std::chrono::seconds(1));
                std::unique_lock<std::mutex> lock2(m2, std::defer_lock);
                printf("func1 lock m2\n");
                std::lock(m1, m2);
                printf("func1 std lock\n");

                m1.unlock();
                m2.unlock();

            }
© www.soinside.com 2019 - 2024. All rights reserved.