Библиотека boost (до стандарта C ++ 11), предлагала поддержку потоков. В рамках своей поддержки он также предлагает реализацию «барьера», простого класса, который позволяет синхронизацию. Процитировать повысить сайт:
«Барьер — это простая концепция. Также известная как рандеву, это точка синхронизации между несколькими потоками. Барьер настроен для определенного числа потоков (n), и, когда потоки достигают барьера, они должны ждать, пока все n потоков Как только n-й поток достиг барьера, все ожидающие потоки могут продолжаться, и барьер сбрасывается. «
Реализация основной функции барьера (ожидания), начиная с Boost 1.54, показана ниже:
bool wait()
{
boost::mutex::scoped_lock lock(m_mutex);
unsigned int gen = m_generation;
if (--m_count == 0)
{
m_generation++;
m_count = m_threshold;
m_cond.notify_all();
return true;
}
while (gen == m_generation)
m_cond.wait(lock);
return false;
}
Видно, что барьер можно использовать многократно: после постройки его не нужно разрушать после первого использования.
Мой вопрос сейчас: для чего нужна переменная m_generation? Я предполагаю, что у авторов библиотеки повышения была причина включить это. Он увеличивается каждый раз, когда барьер сбрасывается / готов к повторному использованию, но с какой целью? Это приватная переменная, поэтому она не может быть прочитана извне. Эту же проблему можно легко решить с помощью простой внутренней переменной bool внутри функции wait () без использования закрытой переменной класса.
В двух словах, m_generation
необходимо иметь дело с ложные пробуждения.
Счетчик генерации используется вместе с условной переменной, чтобы сообщить всем потокам, ожидающим на барьере, что они могут продолжить:
Когда есть m_threshold
потоков, которые достигли барьера, его номер генерации увеличен, и переменная условия сигнализируется. Это заставляет ожидающие потоки (то есть те, которые достигли барьера ранее) просыпаться от m_cond.wait(lock)
,
Теперь ожидающие потоки могут проснуться от m_cond.wait(lock)
за другие причины. Это где m_generation
приходит: если это изменилось, то барьер был сброшен, и поток может продолжаться. Если m_generation
все еще содержит то же значение, поток должен вернуться в m_cond.wait(lock)
,
Наличие автоматической переменной внутри wait()
не будет достигать этого, так как каждый поток будет иметь свой собственный экземпляр.