Concurrency and parallelism
CP.42
Не `wait` без условия
Причина
wait без условия может пропустить пробуждение или проснуться просто, чтобы обнаружить, что нет работы.
Плохой пример
std::condition_variable cv;
std::mutex mx;
void thread1()
{
while (true) {
// do some work ...
std::unique_lock<std::mutex> lock(mx);
cv.notify_one(); // wake other thread
}
}
void thread2()
{
while (true) {
std::unique_lock<std::mutex> lock(mx);
cv.wait(lock); // might block forever
// do work ...
}
}
Здесь, если какой-то другой thread потребляет уведомление thread1, thread2 может ждать вечно.
Пример
template<typename T>
class Sync_queue {
public:
void put(const T& val);
void put(T&& val);
void get(T& val);
private:
mutex mtx;
condition_variable cond; // this controls access
list<T> q;
};
template<typename T>
void Sync_queue<T>::put(const T& val)
{
lock_guard<mutex> lck(mtx);
q.push_back(val);
cond.notify_one();
}
template<typename T>
void Sync_queue<T>::get(T& val)
{
unique_lock<mutex> lck(mtx);
cond.wait(lck, [this] { return !q.empty(); }); // prevent spurious wakeup
val = q.front();
q.pop_front();
}
Теперь, если очередь пуста, когда поток, выполняющий get(), пробуждается (например, потому что другой поток добрался до get() до неё), он немедленно вернётся в спящее состояние, ожидая.
Применение
Отмечайте все wait без условий.