мы с коллегой обсуждали гипотетическую проблему, когда кто-то хотел бы реализовать мьютекс спин-блокировки с std::atomic_flag
, но также реализовать эту спин-блокировку не как while (true), а как
while(true)
{
cnt=0;
while (cnt<yieldAfterTries)
{
//try to get lock
cnt++;
}
std::this_thread::yield();
// if got lock do work and then break;
}
По сути, идея заключается в том, что поток не может блокировать другие «на очень долгое время», даже если он имеет приоритет в реальном времени, потому что он даст результат через некоторое время … но когда я увидел
спецификация std :: yield Я был удивлен, что это предложение, а не обязательная вещь.
Предоставляет подсказку для реализации, чтобы перенести исполнение
потоки, позволяющие другим потокам работать.
http://en.cppreference.com/w/cpp/thread/yield
Так может ли это быть проблематичным?
Я написал код, очень похожий на ваш, и измерил влияние yield
в условиях высокой конкуренции. Я нашел применение yield
таким образом выгодно для общей пропускной способности системы.
Фактическая спецификация не отличается по духу от того, что вы цитируете, но вот точная спецификация из 30.3.2 [thread.thread.this], параграфы 2 и 3:
void this_thread::yield() noexcept;
Последствия: Предлагает реализацию возможность перенести.
Синхронизация: Никто.
Если реализация реализует yield
Например, в случае отсутствия операции это повлияет только на производительность вашего кода, а не на его корректность. Отказ спин-блокировки в конечном итоге будет прерван даже без yield
, Но это также с большей вероятностью излишне нагружает процессор, снижая общую производительность системы.
Планировщик ОС будет автоматически блокировать спин-блокировку, что делает этот код ненужным. ОС автоматически переключится на другой поток, когда один поток займет свою долю времени. Вот почему доходность является подсказкой. Например, в «Полностью честном расписании» в Linux вызов yield часто приводит к ненужным переключениям контекста из-за того, что расписание пытается исправить поток, который не получает за это достаточно времени.
Ваша попытка получить спин-блокировку ничего не заблокирует, только удержание спин-блокировки приведет к блокировке других вещей.