All, Referring to the question in std::lock still caused deadlock
I still couldn't figure what is the problem in the below code. Can somebody please explain the problem and how to fix this? Why does it get hung? Pls help.
#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;
}
Output seen:
func1 lock m1
func2 lock m2
func1 lock m2
func1 std lock
func2 lock m1
----- Hung here.
Why doesn't func2 proceed even though func1 has released both the mutexes?
Instead of :
std::lock(m1, m2);
use :
std::lock(lock1, lock2);
More details (including an example) can be found on the reference page for std::lock
.
When you call std::lock(m1, m2)
, the two mutexes are locked directly. Neither of the std::unique_lock
s (lock1
and lock2
) are aware of this, and thus they can not unlock the mutexes.
So, when func1
ends both mutexes are still locked, and func2
cannot proceed past the std::lock(m1, m2)
line.
When you call std::lock(lock1, lock2)
, the std::unique_lock
s (lock1
and lock2
) are aware of this - they now own the locks, and are responsible for unlocking them (which happens when they go out of scope).
So, when func1
ends both mutexes are unlocked, and func2
can proceed past the std::lock(lock1, lock2)
line. And all is well.