是否有其他方法可以捕获带有条件变量的潜在遗漏信号?

Cor*_*lks 1 c++ multithreading c++11

请考虑以下简化示例:

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

std::mutex mutex;
std::condition_variable cv;
bool cv_flag = false; // I'm talking about this flag here

void startThread1()
{
    std::cout << "thread 1 prints first\n";
    {
        // Set the flag (lock to be safe)
        std::unique_lock<std::mutex> lock(mutex);
        cv_flag = true;
    }
    cv.notify_one();
}

void startThread2()
{
    std::unique_lock<std::mutex> lock(mutex);
    if (!cv_flag)
    {
        cv.wait(lock);
    }

    std::cout << "thread 2 prints second\n";
}

int main()
{
    std::thread thread1(startThread1);
    std::thread thread2(startThread2);

    thread1.join();
    thread2.join();
}
Run Code Online (Sandbox Code Playgroud)

这里,cv_flag用于确保线程2没有锁定,wait()如果线程1已经发送了通知notify_one().没有它,线程2可能会锁定并且wait() 线程1已经调用之后notify_one(),导致无限期挂起,因为线程2正在等待已经发生的事情.

我已经看到很多像这样的代码,其中cv_flag仅用于检测可能错过的通知.

这真的是唯一的方法吗?最干净最简单的?我想如果你可以这样做会很棒:

std::mutex mutex;
std::condition_variable cv;
// no more need for cv_flag

void startThread1()
{
    std::cout << "thread 1 prints first\n";
    cv.notify_one();
}

void startThread2()
{
    std::unique_lock<std::mutex> lock(mutex);
    cv.wait_unless_already_notified(lock); // Unfortunately, this function doesn't exist

    std::cout << "thread 2 prints second\n";
}
Run Code Online (Sandbox Code Playgroud)

有什么相似的wait_unless_already_notified()吗?如果没有,是否有技术原因不存在?

编辑:更改信号/信号引用以通知/通知/通知消除歧义.

Die*_*ühl 7

条件变量不用于检测信号!条件变量的目的是等待一个或多个线程完成某些可被检测为未完成的线程.该信号仅表示另一个线程已经改变某些东西,等待线程应该重新评估它正在等待的条件.除了发送到条件变量的信号之外,还需要更改其他内容以等待.如果要检测另一个线程是否刚刚发送了一些信号,则需要另一个线程来设置相应的指示.

请注意,您的代码有问题:wait()由于发送信号,不一定会唤醒.它可以唤醒由于虚假唤醒而没有另一个线程发出信号.也就是说,您需要始终使用wait()条件的重新评估,例如:

  1. while (!cv_flag) { cv.wait(lock); }
  2. cv.wait(lock, [&](){ return cv_flag; });