Условная переменная против семафора

Когда следует использовать семафор и когда следует использовать условную переменную (CondVar)?

92
задан Karthik Balaguru 20 October 2015 в 17:52
поделиться

3 ответа

Блокировки используются для взаимного исключения. Если вы хотите, чтобы фрагмент кода был атомарным, поставьте вокруг него блокировку. Теоретически для этого можно использовать двоичный семафор, но это особый случай.

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

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

//pseudocode
while(!queue.empty())
{
   sleep(1);
}

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

//pseudocode
syncVar.lock.acquire();

while(!queue.empty())
{
   syncVar.wait();
}

//do stuff with queue

syncVar.lock.release();

Предположительно, у вас будет поток где-то еще, который вытаскивает вещи из очереди. Когда очередь пуста, он может вызвать syncVar.signal () , чтобы разбудить случайный поток, который спит на syncVar.wait () (или обычно есть также метод signalAll () или broadcast () для пробуждения всех ожидающих потоков).

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

Семафоры можно использовать аналогично, но я думаю, что их лучше использовать, когда у вас есть общий ресурс, который может быть доступен или недоступен на основе некоторого целого числа доступных вещей. Семафоры хороши для ситуаций производитель / потребитель, когда производители распределяют ресурсы, а потребители их потребляют.

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

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

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

Методы wait () и signal () переменной синхронизации обычно скрыты внутри down () и up () операции семафора.

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

Это не обязательно самое техническое описание, но именно так оно имеет смысл в моей голове.

187
ответ дан 24 November 2019 в 06:25
поделиться

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

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

15
ответ дан 24 November 2019 в 06:25
поделиться

Я записываю переменные состояния при синхронизации монитора. Я обычно видел семафоры и мониторы как два разных стиля синхронизации. Между ними есть различия в том, сколько данных состояния хранится по своей сути и как вы хотите моделировать код, но на самом деле нет никаких проблем, которые можно было бы решить одним, но не другим.

Я предпочитаю кодировать форму монитора; на большинстве языков, с которыми я работаю, все сводится к мьютексам, условным переменным и некоторым вспомогательным переменным состояния. Но семафоры тоже подойдут.

1
ответ дан 24 November 2019 в 06:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: