Из языка документации мне не ясно, нужно ли проверять предикат std :: condition_variable перед ожиданием.
На cppreference есть утверждение:
Any thread that intends to wait on std::condition_variable has to
1. ...
2. check the condition, in case it was already updated and notified
На практике кажется, что проверять не нужно. Я просто беспокоюсь о неопределенном поведении, если не так.
Меня беспокоит ситуация, когда потребитель подключается к сети после производителя (то есть переменная условия была уведомлена одним потоком до того, как другой поток начнет его ждать):
#include <chrono>
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <thread>
#include <vector>
int main() {
std::condition_variable condition_var;
std::mutex mutex;
std::vector<std::thread> threads;
bool flag = false;
// Producer
threads.emplace_back([&]() {
{
std::lock_guard<std::mutex> lock(mutex);
flag = true;
printf("%s\n", "flag = true");
}
condition_var.notify_all();
});
// Consumer
threads.emplace_back([&]() {
std::this_thread::sleep_for(std::chrono::seconds(3));
{
std::unique_lock<std::mutex> lock(mutex);
condition_var.wait(lock, [&]() { return flag; });
printf("%s\n", "Consumer finished");
}
});
for (auto& thread : threads) {
if (thread.joinable()) {
thread.join();
}
}
return 0;
}
В приведенном выше примере производитель запускается и уведомляет переменную условия. После этого потребитель запускается и уходит в режим ожидания на несколько секунд, прежде чем проверять переменную условия. Это практически гарантирует, что потребитель начнет ждать после того, как производитель уведомит переменную условия.
Несмотря на это, код на моем компьютере заканчивается и не зависает бесконечно. Фактически, из-за того, как быстро он заканчивается, я предполагаю, что это не из-за ложного пробуждения, но я не уверен, как бы я это проверил.