1

I'm trying to implement a simple example of multithreading in C++ (Windows 10, Visual Studio Express).

I have thread T1 that calculates z = x * x, where x and z are global variables. Thread T2 displays z.

I wanted to use locks and a condition variable.

For some reason the execution gets stuck while T1 un unblocked (after cv.wait, probably in the while loop -- high CPU usage). But this does not occur when I add some code (I tried with cout << "x" << endl;) before the cv.notify_one(); in main(). It's very strange.

Thank you in advance for your help!

Here is the code. I removed the parts I put to kill the threads because I do not get to that part of the algorithm -- the issue is before.

#include "stdafx.h" #include <iostream> #include <thread> #include <mutex> #include <condition_variable> using namespace std; mutex m; condition_variable cv; bool datax = 0, dataz = 0, zPrinted = 0; void T1(const int& x, int& z) { do { unique_lock<mutex> lk(m); cv.wait(lk, [] {return (datax); }); if (datax) { z = x * x; datax = 0; dataz = 1; lk.unlock(); while (dataz) cv.notify_one(); } } while (1); } void T2(const int& z) { do { unique_lock<mutex> lk(m); cv.wait(lk, [] {return (dataz); }); if (dataz) { cout << "z = " << z << endl; dataz = 0; zPrinted = 1; lk.unlock(); while (zPrinted) cv.notify_one(); } } while (1); } int main() { int x, z; char c; thread threadT1(T1, cref(x), ref(z)); thread threadT2(T2, cref(z)); do { unique_lock<mutex> lk(m); cout << "Enter x: "; cin >> x; datax = 1; lk.unlock(); while (datax) { cv.notify_one(); } cv.wait(lk, [] {return zPrinted; }); zPrinted = 0; cout << "Continue? (y/n): "; cin >> c; } while (c == 'y'); return 0; } 
3
  • Why are you repeatedly notifying the condition variable in both threads? Commented May 30, 2018 at 9:01
  • or even all 3 threads Commented May 30, 2018 at 9:05
  • 1
    dataz isn't atomic - and you read/write to it outside the lock. Not a good plan. Commented May 30, 2018 at 9:06

2 Answers 2

1

The problem lies here:

lk.unlock(); while (datax) { cv.notify_one(); } cv.wait(lk, [] {return zPrinted; }); // <-- waiting on unlocked mutex zPrinted = 0; 

You are waiting on an unlocked mutex and is undefined behaviour see here under notes.

Sign up to request clarification or add additional context in comments.

Comments

1

Aside from the above indicated problem with waiting on an unlocked mutex:

cv.wait(lk, [] {return zPrinted; }); 

you have threads that are not rejoined and are running infinite loops. Here's a working version with mods to fix these issues:

#include <iostream> #include <thread> #include <mutex> #include <condition_variable> using namespace std; mutex m; condition_variable cv; bool datax = 0, dataz = 0, zPrinted = 0; bool kill = 0; void T1(const int& x, int& z) { do { unique_lock<mutex> lk(m); cv.wait(lk, [] {return (datax+kill); }); if (kill) return; if (datax) { z = x * x; datax = 0; dataz = 1; lk.unlock(); while (dataz) cv.notify_one(); } } while (1); } void T2(const int& z) { do { unique_lock<mutex> lk(m); cv.wait(lk, [] {return (dataz+kill); }); if (kill) return; if (dataz) { cout << "z = " << z << endl; dataz = 0; zPrinted = 1; lk.unlock(); while (zPrinted) cv.notify_one(); } } while (1); } int main() { int x, z; char c; thread threadT1(T1, cref(x), ref(z)); thread threadT2(T2, cref(z)); do { { unique_lock<mutex> lk(m); cout << "Enter x: "; cin >> x; datax = 1; lk.unlock(); while (datax) cv.notify_one(); } { unique_lock<mutex> lk(m); cv.wait(lk, [] {return zPrinted; }); lk.unlock(); } zPrinted = 0; cout << "Continue? (y/n): "; cin >> c; } while (c == 'y'); kill = 1; cv.notify_all(); threadT1.join(); threadT2.join(); return 0; } 

As you see, I introduced a new variable "kill" which, when set to 1, causes both threads to exit their infinite loops, so that they can then be joined.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.