Std :: lock still causes deadlock

std :: lock is used to prevent a deadlock, right? However, in my testing, it still caused a dead end. Could you check my test code to see if I used it incorrectly?

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(2));
    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(2));
    std::unique_lock<std::mutex> lock2(m1, std::defer_lock);
    printf("func2 lock m1\n");
    std::lock(m2, m1);
    printf("func2 std lock\n");
}



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

Exit: func1 lock m1 func2 lock m2 func2 lock m1 func1 lock m2 func2 std lock

Then the console hung ...

+4
source share
1 answer

I think that what you are trying to do does not work: you cannot silently change the mutex under a unique lock. According to the specification, the deferred constructor makes the lock non-possessive, and you cannot change it:

unique_lock(mutex_type& m, defer_lock_t) noexcept;

: unique_lock.

: pm == addressof(m) owns == false.

owns - . .

std::lock:

std::lock(lock1, lock2);
+5

Source: https://habr.com/ru/post/1684238/


All Articles