Я пытался реализовать C ++ пул потоков с STL, который принимает задачи в очередях и отправляет задачи потокам для выполнения.Очередь использует атомную спин-блокировку при нажатии и выталкивании, и, кажется, все работает хорошо со следующим кодом:
void push(const std::function<bool()>& func){
while(in_use.exchange(true, std::memory_order_acquire));
//Actually push the queue, deal with possible exceptions, etc.
in_use.store(false, std::memory_order_release);
}
std::function<bool()> pop(){
while(in_use.exchange(true, std::memory_order_acquire));
//Actually push the queue, deal with possible exceptions, etc.
in_use.store(false, std::memory_order_release);
}
.....//other functions for determining size, etc.
Позже я решил, что std :: this_thread :: yield может быть хорошим выбором вцикл.
(Я включил свой компьютер, когда тестировал задачу, которая помещает ту же задачу в пул, а затем опрашивает пул, когда я устанавливаю приоритет выполнения процесса в режиме реального времени ...)
Однако, когда я изменил строку
while(in_use.exchange(true, std::memory_order_acquire));
на
while(in_use.exchange(true, std::memory_order_acquire)) std::this_thread::yield();
При тех же условиях (задача переносит ту же задачу в пул, с болеезадач, кроме потоков в пуле.) без каких-либо других изменений, все потоки, которые помещаются в главную очередь пула, заблокированы в тупике, все ожидают, что переменная будет выпущена через несколько минут.
IМне было интересно, что именно функция yield может сделать для операции с атомарными переменными, которая может привести к этой проблеме.
PS: Аппаратное обеспечение процессора: Intel Core i5, ОС Windows 10 1803, VS 2017 SDK version 10.0.17763.0.