Можно ли использовать одну переменную условия для двунаправленной синхронизации?

Можно ли использовать одну переменную условия для двунаправленной синхронизации (то есть два разных условия ожидаются в разное время для одной и той же переменной условия)? Я уверен, что не более одного потока будет ожидать переменную условия в любое время. Пример кода ниже иллюстрирует то, о чем я думаю:

#include <condition_variable>
#include <thread>
#include <mutex>
#include <iostream>

std::condition_variable condvar;
std::mutex mutex;
int i;

void even()
{
while (i < 10000) {
std::unique_lock<std::mutex> lock(mutex);
if (i % 2 != 0) {
condvar.notify_one();
condvar.wait(lock, [&](){ return i % 2 == 0; });
}
i++;
std::cout << i << std::endl;
}
condvar.notify_one();
}

void odd()
{
while (i < 10001) {
std::unique_lock<std::mutex> lock(mutex);
if (i % 2 != 1) {
condvar.notify_one();
condvar.wait(lock, [&](){ return i % 2 == 1; });
}
i++;
std::cout << i << std::endl;
}
}

int main()
{
i = 0;
std::thread a(even);
std::thread b(odd);
a.join();
b.join();
}

4

Решение

Да, это совершенно безопасно. Однако я бы не стал привыкать звонить notify_one когда вы действительно хотите уведомить все потоки ожидают выполнения условия, даже если вы «знаете», что будет ожидать только один поток.

6

Другие решения

По сути, уведомление о условной переменной действительно только объявляет, что «возможно, произошло искомое условие».

Единственная проблема, с которой можно столкнуться при двунаправленной связи с одной условной переменной, заключается в том, что поток может быть разбужен уведомлением, когда для него нет доступных данных. Правильное использование условных переменных выполняется в цикле while, поэтому в худшем случае поток видит, что данные недоступны, и возвращается в спящий режим. Это абсолютно безопасно, поэтому возможна двусторонняя связь с одной условной переменной.

Это, как говорится, имеет мало преимуществ для ненужного пробуждения потоков, поэтому обычно предпочтительно иметь один мьютекс, защищающий данные (т.е. вы должны удерживать мьютекс для доступа к данным), и две разные переменные условия, указывающие разные условия. Это минимизирует количество раз, когда вы просыпаетесь от потока, чтобы обнаружить, что у него нет данных для работы (это называется «ложным» уведомлением).

1

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector