在下面的代码中,我将有一个工作线程,它将具有一个主要状态 - 已启动。开始不是线程启动状态,而是阻塞调用最终返回的状态,我已经用随机延迟和注释替换了它。
我在这里尝试的是首先尽快启动工作线程,阻止它阻止呼叫,同时保持started = false
直到它没有返回。一旦它返回,我就会started = true
并通知main
线程的无限循环以启动另一个线程并再次等待。以前的工作线程现在可以继续执行其工作。然后重复这个过程。 新线程的启动必须等待前一个线程的START状态。
但在我之前的question中,有人提到了这个 -
如果在cv.wait运行通知之前调用了cv.notify_one 将被遗漏。在提供的代码中,它很可能会。
目前我尝试以各种方式手动测试它,但无法收到错误,一切都按照我的想法运行。所以我想知道在什么情况下它实际上会错过它,无论如何使其重现,以及如果它是一个问题如何实际解决它?
#include <iostream>
#include <string>
#include <mutex>
#include <condition_variable>
#include <future>
#include <atomic>
#include <chrono>
#include <thread>
#include <random>
std::mt19937_64 eng{std::random_device{}()};
std::uniform_int_distribution<> dist{100, 2000};
std::mutex m;
std::condition_variable cv;
bool started = false;
std::atomic<int> count(0);
void worker_thread()
{
std::unique_lock<std::mutex> lk(m);
int local_cnt = count++;
// some blocking call represented by random delay
std::this_thread::sleep_for(std::chrono::milliseconds{dist(eng)});
std::cerr << "Enter Accept: " << local_cnt << "\n";
started = true;
lk.unlock();
cv.notify_one(); // notify to launch other threads
// complete other work here
std::this_thread::sleep_for(std::chrono::milliseconds{dist(eng) + 2000});
std::cerr << "Exit Accept: " << local_cnt << "\n";
}
int main()
{
while(1){
std::thread(worker_thread).detach();
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, []{return started;});
started = false;
}
}