Creating and avoiding deadlock conditions in C++

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: [code language="cpp"] #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; } [/code] When running this notice that the program hangs and is unable to proceed beyond the second mutex lock acquisition: Deadlock1 Scenario 2: Avoiding Deadlocks The problem of deadlocks can avoided by maintaining consistency in the ordering of the locking and unlocking of mutexes: [code language="cpp"] #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; } [/code] Instead of waiting indefinitely threads A and B are able to complete: Deadlock2

Comments

Popular posts from this blog

Using the Supervisor Controller Pattern to access View controls in MVVM

Getting started with client-server applications in C++

How to send an e-mail via Google SMTP using C#