Преимущества использования условных переменных над мьютексом - PullRequest
23 голосов
/ 20 января 2011

Мне было интересно, каково преимущество в производительности от использования условных переменных по сравнению с мьютекс-блокировками в pthreads.

Я обнаружил следующее: «Без условных переменных программист должен был бы постоянно опрашивать потоки (возможно, в критической секции), чтобы проверить, выполняется ли условие. Это может потребовать очень много ресурсов, поскольку поток будет непрерывно занят в этом упражнении. Переменная условия - это способ достичь той же цели без опроса. " (https://computing.llnl.gov/tutorials/pthreads)

Но также кажется, что вызовы мьютекса блокируются (в отличие от спин-блокировок). Следовательно, если поток (T1) не может получить блокировку, потому что какой-то другой поток (T2) имеет блокировку, T1 переводится в спящий режим ОС и просыпается только тогда, когда T2 снимает блокировку, а ОС предоставляет T1 блокировку. Поток T1 на самом деле не опрашивает, чтобы получить блокировку. Из этого описания кажется, что использование переменных условий не дает выигрыша в производительности. В любом случае опрос не проводится. В любом случае ОС предоставляет преимущество, которое может дать парадигма условной переменной.

Не могли бы вы объяснить, что на самом деле происходит.

Ответы [ 3 ]

46 голосов
/ 20 января 2011

Условная переменная позволяет сигнализировать потоку, когда происходит что-то интересное для этого потока.

Сам по себе мьютекс не делает этого.

Если вам просто нужно взаимное исключение, то переменные условия ничего для вас не делают. Однако, если вам нужно знать, когда что-то происходит, могут помочь условные переменные.

Например, если у вас есть очередь элементов для работы, у вас будет мьютекс для обеспечения согласованности внутренних элементов очереди при доступе к различным потокам производителей и потребителей. Однако, когда очередь пуста, как потребительский поток узнает, когда что-то там есть, чтобы он мог работать? Без чего-то вроде условной переменной нужно было бы опросить очередь, взяв и освободив мьютекс при каждом опросе (иначе поток производителя никогда не мог бы поместить что-либо в очередь).

Использование условной переменной позволяет потребителю обнаружить, что, когда очередь пуста, он может просто ожидать условную переменную, указывая, что в очередь что-то было помещено в нее. Нет опроса - этот поток ничего не делает, пока производитель не поместит что-либо в очередь, а затем не сообщит об условии, что в очереди появился новый элемент.

5 голосов
/ 20 января 2011

Если вы ищете производительность, тогда начните читать об «неблокирующих / неблокирующих» алгоритмах синхронизации потоков.Они основаны на атомарных операциях, которые gcc достаточно любезны.Поиск gcc атомарных операций.Наши тесты показали, что мы можем увеличить глобальное значение с помощью нескольких потоков, используя атомные величины операций быстрее, чем блокировка с помощью мьютекса. Вот пример кода, который показывает, как добавлять элементы в связанный список из нескольких потоков одновременно и без блокировки.

Для спящих и бодрствующих потоков сигналы намного быстрее, чемусловия.Вы используете pthread_kill для отправки сигнала и sigwait для ожидания потока.Мы также проверили это с теми же преимуществами производительности. Вот пример кода.

5 голосов
/ 20 января 2011

Вы ищете слишком много совпадений в двух разных, но связанных вещах: мьютекс и переменная условия.

Обычный подход к реализации мьютекса заключается в использовании флага и очереди. Флаг указывает, удерживается ли мьютекс кем-либо (семафор с одним счетом также будет работать), и очередь отслеживает, какие потоки находятся в очереди, ожидая получения мьютекса исключительно.

Затем условная переменная реализуется как другая очередь, прикрепленная к этому мьютексу. Потоки, которые встали в очередь, чтобы дождаться получения мьютекса, могут - обычно после того, как они его приобрели - могут добровольно выйти из передней части строки и вместо этого попасть в очередь условий. На данный момент у вас есть два отдельных набора официантов:

  • Те, кто хочет приобрести мьютекс исключительно
  • Те, кто ожидает сигнала переменной состояния

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

В игру вступает много сложных деталей, но этот набросок должен дать вам представление о структурах и операциях в игре.

...