【问题标题】:c++ condition variable notification not working as expectedc ++条件变量通知未按预期工作
【发布时间】:2017-08-26 16:23:59
【问题描述】:

我正在尝试在以前的worker_thread 中的工作开始 后立即启动新线程,但可能结束或没有结束。我已经用时间延迟替换了开始和结束的工作。我的代码是:

#include <iostream>
#include <string>
#include <mutex>
#include <condition_variable>
#include <future>
#include <atomic>
#include <chrono>
#include <thread>

std::mutex m;
std::condition_variable cv;
bool started = false;

void worker_thread()
{
    std::unique_lock<std::mutex> lk(m);

    static std::atomic<int> count(1);
    std::this_thread::sleep_for(std::chrono::milliseconds{(count % 5) * 100});
    std::cerr << "Start Worker thread: " << count << "\n";

    started = true;
    lk.unlock();
    cv.notify_one();

    std::this_thread::sleep_for(std::chrono::milliseconds{3000});
    std::cerr << "Exit Worker thread: " << count << "\n";
    ++count;
}

int main()
{
    while(1) {
        std::async(std::launch::async, worker_thread);
        std::unique_lock<std::mutex> lk(m);
        cv.wait(lk, []{return started;});
        started = false;
    }
}

输出如下所示:

Start Worker thread: 1
Exit Worker thread: 1
Start Worker thread: 2
Exit Worker thread: 2
Start Worker thread: 3
Exit Worker thread: 3
Start Worker thread: 4
Exit Worker thread: 4
Start Worker thread: 5
Exit Worker thread: 5

这不是我想要的行为。我想要的是(不完全是)这样的:

Start Worker thread: 1
Start Worker thread: 2
Start Worker thread: 3
Start Worker thread: 4
Exit Worker thread: 1
Exit Worker thread: 3
Exit Worker thread: 4
Exit Worker thread: 2
Start Worker thread: 5
Exit Worker thread: 5

目前下一个线程只有在前一个线程的工作完成时才会启动。但我想在前一个线程开始工作后立即启动下一个线程,而不是等待它结束,只等待开始。

【问题讨论】:

    标签: c++ multithreading concurrency c++14 condition-variable


    【解决方案1】:

    std::async 返回一个std::future 持有函数执行的结果。在您的情况下,它是一个被立即销毁的临时对象。 std::future 的文档说:

    these actions will not block for the shared state to become ready, except that it may block if all of the following are true:

    ✔ 共享状态是通过调用 std::async 创建的

    ✔ 共享状态尚未准备好

    ✔ 这是对共享状态的最后一次引用

    所有这些都是正确的,因此 future 的销毁将阻塞,直到工作函数完成执行。

    你可以创建分离线程来避免这个问题:

    std::thread(worker_thread).detach();
    

    【讨论】:

    • 还有其他问题:如果在 cv.wait 运行之前调用了 cv.notify_one,就会错过通知。在提供的代码中,它很可能会。变量 'started' 由第一个 worker_thread 设置为 true 并保持此状态。
    • @CAF 我忘了在while循环结束时写started = false,已经更新了代码。但我不明白如何解决缺少通知的问题,我不能等待随机的时间,因为启动事件可能需要任何时间..
    • @Laser Focus:如果您在 cv.wait 之前切换 std::async 和 std::unique_lock 语句,则等待肯定会在 notify_one 之前发生。
    • @Laser Focus:条件变量上的等待释放锁,使线程运行......
    猜你喜欢
    • 1970-01-01
    • 2021-12-13
    • 2023-03-14
    • 2021-07-18
    • 1970-01-01
    • 2015-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多