С while(pop_if_present(...))
вы делаете грубую силу занятое ожидание (также называемое вращением) в очереди. Когда очередь пуста, вы теряете циклы, занимая ЦП, пока один из элементов, запущенных на другом ЦП, не будет помещен в очередь другим элементом или ОС решит передать ЦП другому, возможно, не связанному потоку / процессу.
Вы можете увидеть, как это может быть плохо, если у вас есть только один процессор - поток производителя не сможет выдвинуть и, таким образом, остановить вращение потребителя, по крайней мере, до конца временных квантов потребителя плюс накладные расходы переключение контекста . Явная ошибка.
При наличии нескольких процессоров это может быть лучше, если ОС выбирает (или принудительно применяет) поток производителя для запуска на другом процессоре. Это основная идея spin-lock - примитива синхронизации, построенного непосредственно на специальных инструкциях процессора, таких как сравнение-и-замена или условное связывание нагрузки / сохранение и обычно используется внутри операционной системы для связи между обработчиками прерываний и остальной частью ядра, а также для создания конструкций более высокого уровня, таких как семафоры .
С блокировкой pop()
, если очередь пуста, вы вводите sleep wait , т.е. просите ОС перевести поток потребителя в состояние non-schedulable до события - нажать на очередь - происходит из другого потока. Ключевым моментом здесь является то, что процессор доступен для другой (надеюсь полезной) работы. Реализация TBB на самом деле изо всех сил пытается избежать сна, поскольку это дорого (вход в ядро, перепланирование и т. Д.). Цель состоит в том, чтобы оптимизировать обычный случай, когда очередь не пуста и элемент может быть быстро получен.
Хотя выбор действительно прост - всегда в режиме ожидания , т. Е. Блокируйте pop()
, если вам не нужно занято-ожиданием (и это в системах реального времени , Контекст прерывания ОС и некоторые очень специализированные приложения.)
Надеюсь, это немного поможет.