Уведомить с подтверждением в C ++ - PullRequest
0 голосов
/ 16 января 2019

У меня есть какой-то цикл, который работает параллельно и имеет следующие строки:

std::unique_lock <std::mutex> lock(_condLoopMutex);
_condLoopCondition.wait(lock, [this]() { return _conditionReady || _condLoopStopped; });
_conditionReady = false;

// DO SOMETHING

логическая переменная

_conditionReady

устанавливается в параллельном потоке с помощью следующей конструкции:

_conditionReady = true;
_condLoopCondition.notify_one();

Однако иногда моя программа зависает. Кажется, что уведомление приходит между функцией 'wait', передает аргументы и проверяет переменную '_conditionReady'.

Чтобы избежать этого, я реализовал следующее:

while (_conditionReady && !_condLoopStopped)
    {
        _condLoopCondition.notify_one();
        std::this_thread::sleep_for(std::chrono::microseconds(100));
    }

чтобы он продолжал уведомлять до

_conditionReady == false

, что означает, что ожидание окончено.

Это единственное решение этой проблемы - ренотификация до окончания ожидания? Есть ли другой обычный метод решения этих проблем?

Ответы [ 2 ]

0 голосов
/ 16 января 2019

Вам просто нужно удерживать мьютекс, когда вы изменяете переменную _conditionReady. Это позволяет избежать состояния гонки, гарантируя, что переменная не будет изменена между проверкой ее значения и началом ожидания. Убедитесь, что вы освободили мьютекс до или после вызова notify_one, чтобы позволить вашему ожидающему потоку активизироваться (если вы сделаете это после вызова notify, вы можете ввести небольшое снижение производительности, вызвав ожидающий поток, а затем сразу же вернуться в спящий режим как мьютекс блокируется перед повторным пробуждением, когда мьютекс разблокирован). e.g.:

{
  std::unique_lock <std::mutex> lock(_condLoopMutex);
  _conditionReady = true;
}
_condLoopCondition.notify_one();
0 голосов
/ 16 января 2019

Прежде всего, sleep никогда не является решением для ошибок. Он должен действительно генерировать предупреждение компилятора при каждом его использовании, которое передало бы одно и то же сообщение.

Теперь, когда вы изменяете управляющую переменную, которая охраняется условием, это следует делать, удерживая мьютекс - обычно тот же, который используется в вашем cond.wait(). Ваш код этого не делает.

...