I got addicted to learning concurrency again and tried to solve this problem.
In short, I have a class and 3 functions. I need to sync their calls (need to print FirstSecondThird
).
It will become more clear with the code below:
std::function<void()> printFirst = []() { std::cout << "First"; };
std::function<void()> printSecond = []() { std::cout << "Second"; };
std::function<void()> printThird = []() { std::cout << "Third"; };
class Foo {
std::condition_variable cv;
bool mfirst,msecond;
std::mutex mtx;
public:
Foo() {
mfirst = false;
msecond = false;
}
void first(std::function<void()> printFirst) {
std::unique_lock<std::mutex> l(mtx);
printFirst();
mfirst = true;
}
void second(std::function<void()> printSecond) {
std::unique_lock<std::mutex> l(mtx);
cv.wait(l, [this]{return mfirst == true; });
printSecond();
msecond = true;
}
void third(std::function<void()> printThird) {
std::unique_lock<std::mutex> l(mtx);
cv.wait(l, [this] {return (mfirst && msecond) == true; });
printThird();
}
};
int main()
{
Foo t;
std::thread t3((&Foo::third, t, printThird));
std::thread t2((&Foo::second, t, printSecond));
std::thread t1((&Foo::first, t, printFirst));
t3.join();
t2.join();
t1.join();
return 0;
}
And guess what my output is? It prints ThirdSecondFirst
.
How is this possible? Isn't this code prone to DEADLOCK? I mean, when the first thread acquired the mutex in function second
, wouldn't it wait forever because now as mutex is acquired we cannot change variable mfirst
?