#include <iostream>
#include <thread>
#include <exception>
usingnamespace std;
bool doNot = 1; // this bool will prevent func1 and func2 from doing their tasks
thread* fn1; // pointer to t1 thread (defined in main function)
thread* fn2; // pointer to t2 thread (defined in main function)
void func1(bool x)
{
while(doNot) {;} // waiting for changing doNot to false (doing it in main function)
::fn2->join(); // trying to cause deadlock
}
void func2(bool x)
{
while(doNot) {;} // waiting for changing doNot to false (doing it in main function)
::fn1->join(); // trying to cause deadlock
}
int main()
{
// making threads for func1 and func2. I don't know why I've added arguments to func1 & func2
thread t1(func1, 1);
thread t2(func2, 1);
// assigning values to pointers
::fn1 = &t1;
::fn2 = &t2;
::doNot = 0; // STARTING!
t1.join();
t2.join();
cout << "Hello!"; // This code will never be done...
}
The output is:
1 2
terminate called after throwing an instance of 'std::system_error'
what(): Resource deadlock avoided
(That code had do make a deadlock (or try to make it))
What the code does?
It makes 2 threads for 2 functions, and 2 pointers to these threads. Pointers are defined then, so we can start by setting doNot to false.
And then... deadlock!
What is deadlock? So the deadlock is 2 processes waiting for each other. So we made these pointers. func1 and func2 are using these pointers. You can see, the func1 (its thread: t1, pointer to t1: fn1) is waiting for func2 (its thread: t2, pointer to t2: fn2) using fn2 pointer and vice versa. So that's the deadlock.
1 2 3 4 5 6 7 8 9 10
void func1(bool x)
{
while(::doNot) {;} // waiting...
fn2->join(); // now (thread of) func1 waiting for (thread of) func2
}
void func2(bool x)
{
while(::doNot) {;} // waiting...
fn1->join(); // now (thread of) func2 waiting for (thread of) func1
}
That's all! Try to avoid these deadlocks.
You can catch them, obviously.