Какой самый быстрый Метод без гонок для опроса очереди без блокировки?

Допустим, у нас есть очередь с одним потоком-производителем и одним потоком-потребителем без блокировки, и что производитель может долгое время не предоставлять никаких данных. Было бы полезно позволить потребительскому потоку спать, когда в очереди ничего нет (для экономии энергии и освобождения ЦП для других процессов / потоков). Если очередь не была заблокирована, простой способ решить эту проблему - заставить производящий поток блокировать мьютекс, выполнять свою работу, сигнализировать переменную условия и разблокировать, а для потока чтения, чтобы заблокировать мьютекс, подождать переменной условия Прочти, затем разблокируй. Но если мы используем очередь без блокировки, использование мьютекса точно таким же образом снизит производительность, которую мы получаем от использования очереди без блокировки.

Наивное решение состоит в том, чтобы использовать производителя после каждой вставки в очередь. заблокировать мьютекс, указать переменную условия, затем разблокировать мьютекс, сохраняя фактическую работу (вставку в очередь) полностью вне блокировки, и чтобы потребитель делал то же самое, блокируя мьютекс, ожидая переменную условия, разблокируя ее, извлекая все из очереди, затем повторяя, сохраняя чтение очереди вне замка. Однако здесь есть состояние гонки: между выходом читателя из очереди и переходом в режим сна производитель мог вставить элемент в очередь. Теперь читатель перейдет в спящий режим и может оставаться в таком состоянии до тех пор, пока производитель не вставит другой элемент и снова не сигнализирует переменной условия. Это означает, что иногда вы можете столкнуться с тем, что определенные предметы могут занять очень много времени, чтобы пройти через очередь. Если ваша очередь постоянно активна, это не проблема, но если бы он всегда был активен, вы, вероятно, могли бы полностью забыть переменную условия.

AFAICT решение состоит в том, чтобы производитель вел себя так же, как если бы он работал с обычной очередью блокировки потребностей. Он должен заблокировать мьютекс, вставить его в очередь без блокировки, сигнализировать переменную условия, разблокировать. Однако потребитель должен вести себя иначе. Когда он просыпается, он должен немедленно разблокировать мьютекс, а не ждать, пока он не прочитает очередь. Затем он должен извлечь как можно большую часть очереди и обработать ее. Наконец, только когда потребитель думает о сне, он должен заблокировать мьютекс, проверить, есть ли какие-либо данные, а затем, если это так, разблокировать и обработать его или, если нет, то дождаться переменной условия. Таким образом, мьютекс оспаривается реже, чем в случае очереди с блокировкой, но есть s нет риска заснуть с данными, оставшимися в очереди.

Это лучший способ сделать это? Есть ли альтернативы?

Примечание : Под «самым быстрым» я на самом деле подразумеваю «самый быстрый без выделения ядра для многократной проверки очереди», но это не вписывается в заголовок; p

Одна альтернатива : используйте простое решение, но попросите потребителя ждать переменной условия с таймаутом, соответствующим максимальной задержке, которую вы готовы терпеть для элемента, перемещающегося по очереди. Если желаемый тайм-аут довольно короткий, он может быть меньше минимального времени ожидания для вашей ОС или по-прежнему потребляет слишком много ресурсов ЦП.

6
задан Joseph Garvin 21 November 2010 в 04:27
поделиться