Большая часть «правильного» ответа здесь зависит от того, насколько вы цените задержку по сравнению с пропускной способностью, т. Е. Более важно, чтобы этот конкретный поток начинал обработку как можно скорее после того, как ему было сообщено, или что другие потоки получилимаксимальное количество процессорного времени, пока оно ждет? Во многих случаях желаемое также зависит от того, как долго вы ожидаете, что поток будет ждать, прежде чем он будет готов к продолжению.
Прямо сейчас, вы будете заняты ожиданием - то есть, пока вы ждете,вы в какой-то степени удерживаете (хотя бы одно ядро) ЦП, проверяя, может ли он еще работать.
Выполнение Sleep(0)
в основном возвращает текущий поток на назад из очереди потоков, готовых к выполнению и ожидающих выполнения их процессором. Таким образом, если никакой другой поток не ожидает, он все равно будет потреблять 100% процессорного времени. С другой стороны, если другие потоки с таким же приоритетом будут готовы к запуску, они получат шанс на запуск до того, как этот поток будет снова запланирован.
Хотя одно замечание: volatile
на самом деле не определенодля связи между потоками, как это, поэтому вы хотите вместо этого использовать атомарную переменную.
std::atomic<bool> signal { false };
while (!signal)
Sleep(0); // or Sleep(1)
Это может быть хорошо , если вы ожидаете, что это займет всего пару миллисекунд (или что-то в этом порядке) до того, как signal
станет true
, чтобы поток мог продолжить. Так как он не ждет очень долго, он не использует много процессорного времени во время ожидания и (особенно если система слегка загружена) может очень быстро реагировать, когда signal
становится true
.
Если поток, вероятно, будет ждать дольше, чем несколько миллисекунд, вам, вероятно, лучше воспользоваться механизмом, который берет текущий поток и помечает его как не готовый к запуску, но вместо этого ожидает некоторый объект ядра, прежде чем он сможет / будетзапланировано снова. Windows предоставляет Event
s для этой цели:
HANDLE signal = CreateEvent(/* ... */);
WaitForSingleObject(signal, INFINITE);
Когда другой код хочет сообщить, что этот поток должен работать, он делает что-то вроде:
SetEvent(signal);
Для этого простого случаяСобытия Windows могут работать хорошо, но в сложных ситуациях получение того, что вам нужно, может привести к разрыву между трудным и совершенно невозможным (хотя большинство случаев, когда это становится трудным, действительно, потому что вы, вероятно, должны использовать что-то иное, чем событие).
Вы также можете использовать условную переменную из стандартной библиотеки, но она немного сложнее. Переменная условия всегда используется вместе с мьютексом, а также с условием, которое вас волнует. Таким образом, использование его для вашего случая будет выглядеть примерно так:
std::atomic<bool> signal;
std::mutex m;
std::condition_variable v;
std::unique_lock<std::mutex> lock(m);
v.wait(lock, [&] { return signal; });
... и для другого кода, сигнализирующего, что этот поток может работать, он будет делать что-то вроде:
std::unique_lock<std::mutex> lock(m);
signal = true;
v.notify_one();
Переменная условия имеет свои преимущества, но она не самая простая в использовании. С другой стороны, как только вы привыкнете к шаблону, это тоже не составит особого труда.