本文介绍了延迟的线程启动-通知所有未唤醒所有线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

尝试:

要在多个线程上延迟启动.

To do a delayed start on multiple threads.

问题:

我创建了下面的示例来证明这一想法,并尝试在x上创建一个竞争条件,以证明所有线程将同时运行.

I've created the example below to prove out the idea and attempted to create a race codition on x to prove out that all the threads would run concurrently.

似乎事情是序列化而不是并行运行-这是所需的行为,但是也许每个线程运行的时间都太短,并且在另一个线程获得服务之前完成了

It seems like things are serialize instead of running in parallel-the desired behavior, but maybe each thread runs for too short a period and finishes before the other onse get serviced

有时,某个线程将卡在cv.wait上---我已经在GDB中查看了它,并且可以看到其中一个线程正坐在第0帧的等待中---这意味着notify_all并没有唤醒所有线程---(这是零星的行为,每运行几次二进制程序都会发生一次

Sometimes a thread will get stuck on the cv.wait --- I've viewed this in GDB and can see one of the threads just sitting on the wait in frame 0 --- meaning the notify_all did not wak ALL the threads --- (this is sporadic behavior and happens every few attempts at running the binary)

询问:

  1. 使用条件变量是否是一种有效的方法,用于以一组期望的行为来延迟启动一组线程,这些线程将全部并行运行?

  1. Is using the condition variable a valid method for performing a delayed startup of a group of threads with the desired behavior that they will all run in parallel?

为什么notify_all()不唤醒所有线程?

Why is the notify_all() not waking ALL the threads?

代码:

// main.cpp
#include <thread>
#include <mutex>
#include <condition_variable>
#include <functional>
#include <atomic>
#include <iostream>
#include <unistd.h>

int main()
{
    std::condition_variable cv;
    std::mutex cv_m;
    int x = 0;
    std::thread t1 = std::thread([&]{std::unique_lock<std::mutex> lk(cv_m); cv.wait(lk); std::cout << "t1 x:" << x++ << std::endl;});
    std::thread t2 = std::thread([&]{std::unique_lock<std::mutex> lk(cv_m); cv.wait(lk); std::cout << "t2 x:" << x++ << std::endl;});
    std::thread t3 = std::thread([&]{std::unique_lock<std::mutex> lk(cv_m); cv.wait(lk); std::cout << "t3 x:" << x++ << std::endl;});
    std::thread t4 = std::thread([&]{std::unique_lock<std::mutex> lk(cv_m); cv.wait(lk); std::cout << "t4 x:" << x++ << std::endl;});
    std::thread t5 = std::thread([&]{std::unique_lock<std::mutex> lk(cv_m); cv.wait(lk); std::cout << "t5 x:" << x++ << std::endl;});
    std::cout << "STARTING" << std::endl;
    cv.notify_all();
    t1.join();
    t2.join();
    t3.join();
    t4.join();
    t5.join();
    std::cout << "DONE" << std::endl;
    return 0;
}

编译:

g++ -std=c++14 main.cpp -lpthread

运行:

./a.out

推荐答案

条件变量是无状态的.如果没有服务员,通知会丢失;可以发送spurios通知.您需要等待共享状态的更改,而不是条件变量发出的信号.

Condition variables are stateless. Notifications get lost if there are no waiters; spurios notifications can be delivered. You need to wait for a change of a shared state, rather than a signal from a condition variable.

std :: condition_variable :

此外,在通知条件变量时,如果需要保留侍者FIFO顺序,则必须保留互斥体.

Also, when notifying a condition variable the mutex must be held if waiter FIFO order needs to be preserved.

修复:

int main()
{
    std::condition_variable cv;
    std::mutex cv_m;
    int x = 0;
    bool start = false;

    auto thread_fn = [&]{
        std::unique_lock<std::mutex> lk(cv_m);
        while(!start)
            cv.wait(lk);
        std::cout << "t1 x:" << x++ << std::endl;
    };

    std::thread t1 = std::thread(thread_fn);
    std::thread t2 = std::thread(thread_fn);
    std::thread t3 = std::thread(thread_fn);
    std::thread t4 = std::thread(thread_fn);
    std::thread t5 = std::thread(thread_fn);

    std::cout << "STARTING" << std::endl;
    {
        std::unique_lock<std::mutex> lock(cv_m);
        start = true;
        cv.notify_all();
    }

    t1.join();
    t2.join();
    t3.join();
    t4.join();
    t5.join();
    std::cout << "DONE" << std::endl;
}

这篇关于延迟的线程启动-通知所有未唤醒所有线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

05-26 05:03
查看更多