c++multithreadingvisual-studiocondition-variable

Error when exiting a program using `std::condition_variable`


I've a problem with some code with the same logic of the following one:

#include <mutex>
#include <condition_variable>
#include <thread>
#include <iostream>

int main() {
  std::condition_variable myCV;
  std::mutex myMutex;
  std::unique_lock myLock(myMutex);
  bool isRunning{ true };

  std::jthread myThread([&isRunning, &myCV, &myLock]() {
    while (isRunning) {
      myCV.wait(myLock);
      // do some work here
    }
    std::cout << "Exited from myThread while loop." << std::endl;
    });

  for (int i = 0; i < 100; i++) {
    myCV.notify_one();
    std::this_thread::sleep_for(std::chrono::milliseconds(20));
    std::cout << "Test loop " << i << std::endl;
  }

  isRunning = false;
  myCV.notify_one();

  return 0;
}

Basically, I've a loop where i do some work, and when my work is done at every iteration I call a method in another thread for handling the data without blocking the main thread; in order to avoid to create and destruct the thread every time, I'm using a loop inside that thread with a std::condition_variable for starting to manage the data when they are ready.

The logic works well but I've a problem when exiting the program; if I run the code I've an error when the program ends, because the mutex destructor calls abort():

...\stl\src\mutex.cpp(164): unlock of unowned mutex

If I comment the following row myCV.notify_one(); the program continues to run without stopping.

How can I exit the program gracefully without any error? What I'm doing wrong?


Solution

  • Thanks for your comments. The problem was in fact the mutex that was unlocked in a thread different from the one that acquired it. Moving the lock definition inside the thread code solved the problem:

    #include <mutex>
    #include <condition_variable>
    #include <thread>
    #include <iostream>
    
    int main() {
      std::condition_variable myCV;
      std::mutex myMutex;
      bool isRunning{ true };
    
      std::jthread myThread([&isRunning, &myCV, &myMutex]() {
        std::unique_lock myLock(myMutex);
        while (isRunning) {
          myCV.wait(myLock);
          // do some work here
        }
        std::cout << "Exited from myThread while loop." << std::endl;
        });
    
      for (int i = 0; i < 100; i++) {
        myCV.notify_one();
        std::this_thread::sleep_for(std::chrono::milliseconds(20));
        std::cout << "Test loop " << i << std::endl;
      }
    
      isRunning = false;
      myCV.notify_one();
    
      return 0;
    }