其他分享
首页 > 其他分享> > c – 延迟线程启动 – 通知所有不唤醒所有线程

c – 延迟线程启动 – 通知所有不唤醒所有线程

作者:互联网

尝试:

在多个线程上执行延迟启动.

问题:

我已经创建了下面的例子来证明这个想法,并试图在x上创建一个种族代码来证明所有的线程都会同时运行.

似乎事物是序列化而不是并行运行 – 期望的行为,但也许每个线程运行的时间太短并且在另一个onse得到服务之前结束

有时一个线程会卡在cv.wait上 – 我在GDB中看过这个并且可以看到其中一个线程只是在第0帧中等待 – 这意味着notify_all没有唤醒所有线程 – – (这是零星的行为,每次尝试运行二进制文件都会发生)

问:

>使用条件变量是一个有效的方法来执行一组线程的延迟启动,这些线程具有所有并行运行的行为吗?
>为什么notify_all()没有唤醒所有线程?

码:

// 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通知.您需要等待更改共享状态,而不是来自条件变量的信号.

std::condition_variable

When the condition variable is notified, a timeout expires, or a spurious wakeup occurs, the thread is awakened, and the mutex is atomically reacquired. The thread should then check the condition and resume waiting if the wake up was spurious.

此外,在通知条件变量时,如果需要保留服务器FIFO顺序,则必须保持互斥锁.

修正:

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;
}

标签:c,multithreading,c14
来源: https://codeday.me/bug/20191008/1872753.html