Reputation: 63
I'm teaching myself a bit about concurrent programming, specifically using mutexes and threads in C++. I've written the following small example:
#include <iostream>
#include <thread>
#include <mutex>
// #include <chrono>
std::mutex M1,M2;
void task_one () {
std::cout << "AAAA!\n";
M1.lock();
// std::cout << "M1 locked in A\n";
M2.lock();
// std::cout << "M2 locked in A\n";
std::cout << "BBBB!\n";
M2.unlock();
// std::cout << "M2 unlocked in A\n";
M1.unlock();
// std::cout << "M2 unlocked in A\n";
}
void task_two () {
std::cout << "CCCC!\n";
M2.lock();
// std::cout << "M2 locked in B\n";
M1.lock();
// std::cout << "M1 locked in B\n";
std::cout << "DDDD!\n";
// M1.unlock();
// std::cout << "M1 unlocked in B\n";
M2.unlock();
// std::cout << "M2 unlocked in B\n";
}
int main () {
std::thread th1 (task_one);
std::thread th2 (task_two);
th1.join();
th2.join();
// th1.detach();
// th2.detach();
// std::chrono::milliseconds timespan(10);
// std::this_thread::sleep_for(timespan);
return 0;
}
I expected this code to print
AAAA!
CCCC!
and then deadlock when task_one
attempts to acquire the lock on M2 (because task_two
will have already acquired that lock).
However, it prints
AAAA!
BBBB!
CCCC!
DDDD!
Why isn't there a deadlock? In addition, is this an example of a race condition, or is this code thread-safe? I think that there is a race condition because if task_one
can acquire a lock on M2 before task_two
can, then everything will execute (that is, task_one
will finish and then allow task_two
to begin). However, I ran this quite a few times with the same results. Also, if my verbiage as it relates to locks and threads is incorrect, please correct me.
Upvotes: 0
Views: 29
Reputation: 25388
Just because a deadlock can happen (as indeed it can in the code as posted), doesn't mean it always will happen.
In your case, task_one
happens to run to completion before task_two
gets going at all.
Multi-threading is like that: slippery.
Upvotes: 2