The most common cause of a DEADLOCK is not acquiring multiple locks in the same order.
A situation where threads block indefinitely because they are waiting to acquire access to resources currently locked by other blocked threads.
Let's see an example:
Thread 1 | Thread 2 |
---|---|
Lock A | Lock B |
.. Do some processing | ..do some processing |
Lock B | Lock A |
.. Do some more processing | ..Do some more processing |
Unlock B | Unlock A |
Unlock A | Unlock B |
NOTE: In some situations, what is going to happen is that when Thread 1 tries to acquire Lock B, it gets blocked because Thread 2 is already holding lock B.
And from Thread 2's perspective, it is blocked on acquiring lock A, but cannot do so because Thread 1 is holding lock A.
Thread 1 cannot release lock A unless it has acquired lock B and so on.
In other words, your program is hanged at this point.
#include <iostream> #include <string> #include <thread> #include <mutex> using namespace std; std::mutex muA; std::mutex muB; void CallHome_AB(string message) { muA.lock(); //Some additional processing std::this_thread::sleep_for(std::chrono::milliseconds(100)); muB.lock(); cout << "Thread " << this_thread::get_id() << " says " << message << endl; muB.unlock(); muA.unlock(); } void CallHome_BA(string message) { muB.lock(); //Some additional processing std::this_thread::sleep_for(std::chrono::milliseconds(100)); muA.lock(); cout << "Thread " << this_thread::get_id() << " says " << message << endl; muA.unlock(); muB.unlock(); } int main() { thread t1(CallHome_AB, "Hello from Jupiter"); thread t2(CallHome_BA, "Hello from Pluto"); t1.join(); t2.join(); return 0; }
NOTE: If you run this, it will hang.
So, what can you do about it?
std::scoped_lock lock{muA, muB};