问题描述
尝试:
要在多个线程上延迟启动.
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)
询问:
-
使用条件变量是否是一种有效的方法,用于以一组期望的行为来延迟启动一组线程,这些线程将全部并行运行?
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.
此外,在通知条件变量时,如果需要保留侍者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;
}
这篇关于延迟的线程启动-通知所有未唤醒所有线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!