A short and to-the-point post illustrating how a deadlock situation can be created in C++, together with a possible strategy for avoiding such a condition.
I’m am using the boost libraries to implement threads and mutexes, but it should be possible to the standard library implementations std::thread, std::mutex etc as well.
Scenario 1: Deadlock Condition
If thread A is executing and isn’t holding mutex lock 1 yet and thread B acquires mutex lock 2, neither of the threads can continue past the second lock acquisition:
#include <iostream>
#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
boost::mutex mutex1, mutex2;
void ThreadA()
{
// Creates deadlock problem
mutex2.lock();
std::cout << "Thread A" << std::endl;
mutex1.lock();
mutex2.unlock();
mutex1.unlock();
}
void ThreadB()
{
// Creates deadlock problem
mutex1.lock();
std::cout << "Thread B" << std::endl;
mutex2.lock();
mutex1.unlock();
mutex2.unlock();
}
void ExecuteThreads()
{
boost::thread t1( ThreadA );
boost::thread t2( ThreadB );
t1.join();
t2.join();
std::cout << "Finished" << std::endl;
}
int main()
{
ExecuteThreads();
return 0;
}
When running this notice that the program hangs and is unable to proceed beyond the second mutex lock acquisition:
Scenario 2: Avoiding Deadlocks
The problem of deadlocks can avoided by maintaining consistency in the ordering of the locking and unlocking of mutexes:
#include <iostream>
#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
boost::mutex mutex1, mutex2;
void ThreadA()
{
// Solves deadlock problem
mutex1.lock();
std::cout << "Thread A" << std::endl;
mutex2.lock();
mutex2.unlock();
mutex1.unlock();
}
void ThreadB()
{
// Solves deadlock problem
mutex1.lock();
std::cout << "Thread B" << std::endl;
mutex2.lock();
mutex1.unlock();
mutex2.unlock();
}
void ExecuteThreads()
{
boost::thread t1( ThreadA );
boost::thread t2( ThreadB );
t1.join();
t2.join();
std::cout << "Finished" << std::endl;
}
int main()
{
ExecuteThreads();
return 0;
}
Instead of waiting indefinitely threads A and B are able to complete:


Comments
One response to “Creating and avoiding deadlock conditions in C++”
Great example. Thanks for sharing. Which of the four necessary and sufficient conditions would this be considered as solving the deadlock problem? To me it seems like the reordering of locking/unlocking mutexes would be solving the circular wait..? I just wanted to clarify that. Thanks!