Переменные состояния - отличный примитив синхронизации, и в моем личном опыте это инструмент, с которым я отвечаю, до 95% ситуаций синхронизации/потоковой передачи.
Если у вас нет C++ 11, вы можете использовать boost::condition_variable
.
В этом случае у вас не будет версии wait
с предикатом (потому что нет lambdas в C++ 03). Поэтому вам абсолютно необходимо запомнить цикл проверки состояния. Как объяснено в документации:
boost::unique_lock<boost::mutex> lock(mut);
while (projects_completed < 12)
{
wait(lock);
}
сравни:
http://www.boost.org/doc/libs/1_58_0/doc/html/thread/synchronization.html#thread.synchronization.condvar_ref
Это потому, что вы не получаете никаких гарантий, что условие выполнено после уведомления, в частности потому, что замок может быть приобретено другим потоком в междоузлии между разблокировкой и уведомлением. Также может произойти ложное пробуждение.
Я также написал статью об этом:
http://www.gamedev.net/page/resources/_/technical/general-programming/multithreading-r3048
Кроме того, если вы используете timed_wait
(и я рекомендую его, как это часто снижает priority inversion), еще одна ловушка, чтобы не попасть в это тайм-аут из-за петли вы не можете использовать относительный тайм-аут (например, 2 секунды), вам нужно абсолютное системное время, определенное до ввода цикла.
boost
делает его очень чистым с этой техникой:
system_time const timeout = get_system_time() + posix_time::seconds(2);
О картине спин блокировки, предложенной Барри, я не рекомендовал бы это, если вы не в реальной среде времени, как игровая приставка 3/4 или эквивалент. Или, если вы не уверены, что это не продлится более нескольких секунд.
С помощью блокировки спина вы теряете электроэнергию, и у вас не останется шанса, что CPU войдет в состояние ожидания (шаг скорости c.f intel).
Это также имеет последствия для справедливости и планирования, как описано в Википедии:
https://en.wikipedia.org/wiki/Spinlock
Наконец, если у вас нет импульс, так как Windows Vista мы получаем уроженцы Win32 функции:
SleepConditionVariableCS
https://msdn.microsoft.com/en-us/library/windows/desktop/ms686301(v=vs.85).aspx
Что вы имеете в виду «block»?, Вы работаете с несколькими задачами? вы хотите выйти из функции/метода? –
YEs Класс DoWork использует несколько потоков, которые увеличивают атомную переменную-член. Я бы хотел, чтобы someMethod() не возвращался, пока атомная переменная не имеет определенного значения. 10 – MistyD