无法设置条件变量

Not able to set conditional Variable

在下面的代码中,我在函数 waitingForWork() 中等待条件变量,但从未调用 doTheCleanUp()

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <iostream>           // std::cout
#include <thread>          // std::thread
#include <mutex>              // std::mutex, std::unique_lock
#include <condition_variable> // std::condition_variable


std::mutex mtx;
std::condition_variable cv;
bool stop=false;

void stopTheWait()
{
    sleep(5);
    printf("stopping the wait.. \n\n");
    std::lock_guard<std::mutex> lck(mtx);
    stop = true;
    cv.notify_all();
}

void doTheCleanUp()/* is never called*/ {
    printf("clean up... \n\n");
}

void waitingForWork(){
    printf("wait for ever... \n\n");

    std::unique_lock<std::mutex> lck(mtx);
    cv.wait(lck, []{ return stop;});
    doTheCleanUp();
    printf("clean Up Done, now end wait... \n\n");
}


int main()
{
    printf("in main... \n");
   
   std::unique_lock<std::mutex> lck(mtx);

   std::thread t1(stopTheWait);
   
   waitingForWork();
   
   printf("exiting main...\n");
   sleep(1);
   
   return 0;
}

main() 正在锁定 std::mutex,然后在同一个线程中调用 waitingForWork(),它会再次尝试锁定 std::mutexThis is undefined behavior:

If lock is called by a thread that already owns the mutex, the behavior is undefined: for example, the program may deadlock. An implementation that can detect the invalid usage is encouraged to throw a std::system_error with error condition resource_deadlock_would_occur instead of deadlocking.

没有充分理由main()获得那个初始锁,摆脱它:

int main()
{
    printf("in main... \n");
   
   //std::unique_lock<std::mutex> lck(mtx); // <-- HERE

   std::thread t1(stopTheWait);
   
   waitingForWork();
   
   printf("exiting main...\n");
   sleep(1);
   
   return 0;
}

注意,一般情况下,如果必须在同一个线程中多次锁定一个互斥锁,则需要使用std::recursive_mutex代替:

A calling thread owns a recursive_mutex for a period of time that starts when it successfully calls either lock or try_lock. During this period, the thread may make additional calls to lock or try_lock. The period of ownership ends when the thread makes a matching number of calls to unlock.


另请注意,您需要在 t1 超出范围并被销毁之前调用 t1.join()t1.detach(),否则其 destructor 将中止调用进程:

If *this has an associated thread (joinable() == true), std::terminate() is called.

你这里有一个错误:

void waitingForWork(){
    printf("wait for ever... \n\n");

    std::unique_lock<std::mutex> lck(mtx);         // This lock is bad.
                                                   // you already locked the
                                                   // mutex in main.
                                                   //
                                                   // locking it again is UB

    cv.wait(lck, []{ return stop;});               // Once you enter wait()
                                                   // lock will be released
                                                   // until you are notified.
    doTheCleanUp();
    printf("clean Up Done, now end wait... \n\n");
}