Разница между счетными и двоичными семафорами

В чем разница между подсчетом и двоичным семафором.

Что я видел где-то, так это то, что оба могут контролировать N процессов, которые запросили ресурс. Оба взяли и свободные государства.

Есть ли какие-либо ограничения на количество ресурсов, которые может защитить двоичный семафор и счетный семафор?

Оба позволяют только одному процессу использовать ресурс одновременно...

Есть ли другая разница? Являются ли вышеупомянутые свойства правильными?

3 ответа

Решение

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

Разница заключается в следующем:

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

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

Для получения дополнительной информации, посмотрите на эту ссылку.
http://www.chibios.org/dokuwiki/doku.php?id=chibios:articles:semaphores_mutexes

РЕДАКТИРОВАТЬ
Максимальное значение, которое может принять счетный семафор, - это количество процессов, которые вы хотите разрешить в критическую секцию одновременно.
Опять же, у вас может быть случай, когда вы хотите исключить определенный ресурс, но вы знаете, что к этому ресурсу может обращаться максимальное количество процессов (скажем, X), поэтому вы устанавливаете счетный семафор со значением X.

Это позволило бы процессам X одновременно получать доступ к этому ресурсу; все же процесс X+1 должен был бы ждать, пока один из процессов в критической секции не выйдет.

Существуют две основные концепции создания параллельных программ - синхронизация и взаимное исключение. Мы увидим, как эти два типа блокировок (семафоры, в более общем смысле, являются своего рода механизмом блокировки) помогают нам добиться синхронизации и взаимного исключения.

Семафор состоит из двух частей: счетчика и списка задач, ожидающих доступа к определенному ресурсу. Семафор выполняет две операции: wait (P) [это похоже на получение блокировки] и release (V)[аналогично освобождению блокировки] - это единственные две операции, которые можно выполнить с семафором. В двоичном семафоре счетчик логически переходит от 0 до 1. Вы можете думать, что он похож на блокировку с двумя значениями: открыт / закрыт. Счетный семафор имеет несколько значений для счета.

Важно понимать, что счетчик семафоров отслеживает количество задач, которые не нужно блокировать, т. Е. Они могут добиться прогресса. Задачи блокируются и добавляются в список семафоров только тогда, когда счетчик равен нулю. Следовательно, задача добавляется в список в процедуре P(), если она не может быть выполнена, и "освобождается" с помощью процедуры V ().

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

ех. Синхронизация:

thread A{
semaphore &s; //locks/semaphores are passed by reference! think about why this is so.
A(semaphore &s): s(s){} //constructor
foo(){
...
s.P();
;// some block of code B2
...
}

//thread B{
semaphore &s;
B(semaphore &s): s(s){} //constructor
foo(){
...
...
// some block of code B1
s.V();
..
}

main(){
semaphore s(0); // we start the semaphore at 0 (closed)
A a(s);
B b(s);
}

В приведенном выше примере B2 может выполняться только после того, как B1 завершил выполнение. Предположим, что поток A выполняется, выполняется первым - получает sem.P () и ждет, так как счетчик равен 0 (закрыт). Приходит поток B, завершается B1, а затем освобождается поток A, который затем завершает B2. Таким образом, мы достигаем синхронизации.

Теперь давайте посмотрим на взаимное исключение с помощью двоичного семафора:

thread mutual_ex{
semaphore &s;
mutual_ex(semaphore &s): s(s){} //constructor
foo(){
...
s.P();
//critical section
s.V();
...
...
s.P();
//critical section
s.V();
...

}

main(){
semaphore s(1);
mutual_ex m1(s);
mutual_ex m2(s);
}

Взаимное исключение также довольно просто - m1 и m2 не могут одновременно войти в критическую секцию. Таким образом, каждый поток использует один и тот же семафор, чтобы обеспечить взаимное исключение для его двух критических секций. Теперь возможно ли иметь больший параллелизм? Зависит от критических разделов. (Подумайте, как еще можно использовать семафоры для достижения взаимного исключения... подсказка: мне обязательно нужно использовать только один семафор?)

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

Давайте возьмем самое простое из двух:

Синхронизация с использованием счетного семафора. Допустим, у вас есть 3 задачи - № 1 и 2, которые вы хотите выполнить после 3. Как бы вы разработали свою синхронизацию?

thread t1{
...
s.P();
//block of code B1

thread t2{
...
s.P();
//block of code B2

thread t3{
...
//block of code B3
s.V();
s.V();
}

Таким образом, если ваш семафор начинается закрытым, вы гарантируете, что блоки t1 и t2 будут добавлены в список семафоров. Затем приходит все важное t3, заканчивает свою деятельность и освобождает t1 и t2. В каком порядке они освобождены? Зависит от реализации списка семафоров. Может быть FIFO, может основываться на каком-то конкретном приоритете и т. Д. (Примечание: подумайте, как бы вы расположили свои P и V; если вы хотите, чтобы t1 и t2 выполнялись в каком-то определенном порядке, и если вы не знали о реализации семафора)

(Узнайте: что произойдет, если число V больше, чем число P?)

Взаимное исключение Использование счетных семафоров: я хотел бы, чтобы вы создали для этого свой собственный псевдокод (помогает вам лучше понимать вещи!), Но фундаментальная концепция такова: счетный семафор counter = N позволяет N задачам свободно входить в критическую секцию, Это означает, что у вас есть N задач (или потоков, если хотите), попадающих в критическую секцию, но N+1-я задача блокируется (входит в наш любимый список заблокированных задач) и пропускается только тогда, когда кто-то из V семафор. Хотя бы один раз. Таким образом, счетчик семафоров, вместо того, чтобы колебаться между 0 и 1, теперь идет между 0 и N, позволяя N задачам свободно входить и выходить, не блокируя никого!

Теперь, зачем вам такой странный замок? Разве не весь смысл взаимного исключения, чтобы не позволить больше чем одному парню получить доступ к ресурсу?? Считать. (Подсказка... у вас не всегда есть только один диск на вашем компьютере, не так ли...?)

Задуматься: достигнуто ли взаимное исключение только с помощью счетного семафора? Что если у вас есть 10 экземпляров ресурса и 10 потоков входят (через счетный семафор) и пытаются использовать первый экземпляр?

Основное различие между счетным и двоичным семафором заключается в том, что:

  1. Двоичный семафор не может обрабатывать ограниченное ожидание как его переменную, которая содержит двоичное значение. Подсчет семафора Он может обрабатывать ограниченное ожидание, поскольку он преобразовал переменную в структуру с очередью.
  2. Strcuture реализация Бинарный семафор: int s;

    Подсчет семафора: Struct S { int s; Очередь q; }

При использовании счетного семафора теперь процесс, получивший CS (Critical Section), теперь должен ждать, пока другой получит CS, так что ни одного процесса не нужно. Каждый процесс получает шанс на CS.

Другие вопросы по тегам