Семафоры и мьютексы / условные переменные являются хорошими, очень высокопроизводительными примитивами, которые подходят для использования между потоками или между процессами.
Все они основаны на идее (и, как правило, на реальности) тестирования и установки или других элементарных операций, выполняемых над общей памятью.
Если вы планируете распространять свои процессы по сети, то семафоры и мьютексы могут быть вам неподходящими - они работают только на одной машине. Трубы и розетки, как правило, расширяются в сети.
Краткое описание мьютексов, условных переменных и семафоров:
Мьютексы
Мьютекс - это примитив, который может быть заблокирован или разблокирован. Процесс / поток, который заблокировал это, должен быть тем, чтобы разблокировать это. Этот аспект владение позволяет операционной системе применять некоторые интересные оптимизации, такие как наследование приоритетов и протокол потолка приоритета (чтобы избежать инверсии приоритетов). однако , мьютекс не имеет счетчика, связанного с ним. В общем, вы не можете заблокировать уже заблокированный мьютекс и сохранить память, которая была «заблокирована дважды» (я думаю, что есть некоторые расширения, которые позволяют это сделать, но они не доступны везде)
Переменные условия
Мьютекс отлично подходит для ... ну, взаимное исключение. Но что если вам нужно заблокировать условие, связанное с объектом, к которому вы имеете взаимное исключение? Для этого вы используете условную переменную или CV. Резюме связано с мьютексом. Например, скажем, у меня есть очередь входных данных, к которым мои процессы хотят получить доступ. Один захватывает мьютекс, чтобы он мог смотреть в очередь без страха вмешательства. Тем не менее, он находит очередь пустой и хочет ждать, пока что-то поступит в очередь. Поэтому он ожидает переменную условия «очередь не пуста». Интересная часть здесь состоит в том, что, поскольку CV связано с мьютексом, мьютекс получает , автоматически повторно получает , как только передается переменная условия. Таким образом, как только процесс просыпается после ожидания в CV, он знает, что он снова имеет эксклюзивный доступ к очереди. не знает, что на самом деле в очереди есть что-то - возможно, два процесса ждали резюме - одна вещь пришла - и первый приоритет получил и снял «вещь» перед вторая вещь проснулась. Таким образом, всякий раз, когда вы используете CV, вам нужно ПРОВЕРИТЬ условие, например:
mutex_enter(m);
while (! condition) {
cond_wait(m, c); // drop mutex lock; wait on cv; reacquire mutex
}
//processing related to condition
mutex_exit(m);
семафоры
ОК, это мьютексы и условные переменные. Семафоры проще. Их можно увеличивать и уменьшать любыми процессами. У них есть память - они считают - так что вы можете использовать их, чтобы определить, сколько из условий произошло. Не так с переменными состояния. Кроме того, поскольку семафоры могут быть уменьшены одним процессом и увеличены другим, они не имеют аспекта владения - поэтому нет наследования приоритетов, предотвращение инверсии приоритетов невозможно.
Теперь, наконец, все эти механизмы требуют общей памяти для эффективной реализации. Это может быть хорошо для вас, но имейте в виду - если вы считаете, что ваше приложение может в конечном итоге распространяться, то мьютексы, условные переменные и семафоры могут не подойти Трубы и разъемы, хотя и требуют гораздо больших затрат, могут быть достаточно просто расширены по сети.