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 Tesseract optical character recognition (OCR) library in Visual Studio

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