Рубріки: Теория

Что такое семафоры в программировании и зачем они нужны?

Светлана Лазутина

Семафор — инструмент для управления синхронизацией. Это целочисленная переменная, которую одновременно используют сразу несколько процессов. Основная цель использования семафора — это синхронизация процессов и управление доступом к общему ресурсу в многопроцессорной среде. 

У семафоров них есть две основные операции:

  • Операция ожидания уменьшает значение аргумента S, если оно положительное. Если значение S отрицательно или равно нулю, операция не выполняется:
wait(S)
{
   while (S<=0);
   S--;
}
  • Операция подачи сигнала увеличивает значение своего аргумента S:
signal(S)
{
   S++;
}

Есть два типа семафоров:

  • Универсальный или считающий семафор — это семафор с целочисленными значениями и неограниченной областью значений. Эти семафоры используются для координации доступа к ресурсам, где счетчик семафоров — это количество доступных ресурсов. Если ресурсы добавляются, счетчик семафоров автоматически увеличивается, а если ресурсы удаляются, счетчик уменьшается. Считающий семафор используется для работы с несколькими процессами и решения проблем синхронизации.
  • Двоичный семафор — имеет значение, ограниченное 0 и 1. Операция ожидания работает только тогда, когда семафор равен 1, а операция сигнала завершается успешно, когда семафор равен 0. Если вам знаком механизм работы мьютексов, то может показаться, что нет разницы, что использовать — двоичный семафор или мьютекс.

Но на самом деле семафор — это сигнальный механизм, а мьютекс — это механизм блокировки. 

Работа семафоров на примерах из жизни

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

Работа семафора на примере очереди в банкомат / media.geeksforgeeks.org

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

Работа семафора на примере очереди в ресторан / media.geeksforgeeks.org

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

Наглядная схема работы семафора / media.geeksforgeeks.org

Пример кода с использованием семафоров

Давайте посмотрим, как семафоры работают в коде C++: 

#include<iostream>

#include<mutex>

using namespace std;

struct semaphore
{
    int mutex;
    int rcount;
    int rwait;
    bool wrt;
};

void addR(struct semaphore *s)
{
    if(s->mutex == 0 && s->rcount == 0)
    {
        cout<<"\nSorry, File open in Write mode.\nNew Reader added to queue.\n";
        s->rwait++;
    }
    else
    {
        cout<<"\nReader Process added.\n";
        s->rcount++;
        s->mutex--;
    }
return ;
}

void addW(struct semaphore *s)
{
    if(s->mutex==1)
    {
        s->mutex--;
        s->wrt=1;
        cout<<"\nWriter Process added.\n";
    }
    else if(s->wrt) 
        cout<<"\nSorry, Writer already operational.\n";
    else
        cout<<"\nSorry, File open in Read mode.\n";
return ;
}
void remR(struct semaphore *s)
{
    if(s->rcount == 0) cout<<"\nNo readers to remove.\n";
    else
    {
        cout<<"\nReader Removed.\n";
        s->rcount--;
        s->mutex++;
    }
return ;
}
void remW(struct semaphore *s)
{
    if(s->wrt==0) cout<<"\nNo Writer to Remove\n";
   else
   {
        cout<<"\nWriter Removed\n";
        s->mutex++;
        s->wrt=0;
  if(s->rwait!=0)
{
    s->mutex-=s->rwait;
    s->rcount=s->rwait;
    s->rwait=0;
    cout<<"waiting Readers Added:"<<s->rcount<<endl;
}
}
}

int main()
{
struct semaphore S1={1,0,0};
while(1)
{
cout<<"Options :-\n1.Add Reader.\n2.Add Writer.\n3.Remove Reader.\n4.Remove Writer.\n5.Exit.\n\n\tChoice : ";
int ch;
cin>>ch;
switch(ch)
{
case 1: addR(&S1); break;
case 2: addW(&S1); break;
case 3: remR(&S1); break;
case 4: remW(&S1); break;
case 5: cout<<"\n\tGoodBye!";break;
default: cout<<"\nInvalid Entry!";
}
}
return 0;
}

В результате получим:

Options :-
1.Add Reader.
2.Add Writer.
3.Remove Reader.
4.Remove Writer.
5.Exit.

        Choice : 1

Reader Process added.
Options :-
1.Add Reader.
2.Add Writer.
3.Remove Reader.
4.Remove Writer.
5.Exit.

        Choice : 1

Reader Process added.
Options :-
1.Add Reader.
2.Add Writer.
3.Remove Reader.
4.Remove Writer.
5.Exit.

        Choice : 1

Reader Process added.
Options :-
1.Add Reader.
2.Add Writer.
3.Remove Reader.
4.Remove Writer.
5.Exit.

        Choice : 3

Reader Removed.
Options :-
1.Add Reader.
2.Add Writer.
3.Remove Reader.
4.Remove Writer.
5.Exit.

        Choice : 2

Sorry, File open in Read mode.
Options :-
1.Add Reader.
2.Add Writer.
3.Remove Reader.
4.Remove Writer.
5.Exit.

        Choice : 3

Reader Removed.
Options :-
1.Add Reader.
2.Add Writer.
3.Remove Reader.
4.Remove Writer.
5.Exit.

Останні статті

Что такое прокси-сервер: пояснение простыми словами, зачем нужны прокси

Прокси (proxy), или прокси-сервер — это программа-посредник, которая обеспечивает соединение между пользователем и интернет-ресурсом. Принцип…

21.11.2024

Что такое PWA приложение? Зачем необходимо прогрессивное веб-приложение

Согласитесь, было бы неплохо соединить в одно сайт и приложение для смартфона. Если вы еще…

19.11.2024

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

Повсеместное распространение смартфонов привело к огромному спросу на мобильные игры и приложения. Миллиарды пользователей гаджетов…

17.11.2024

Google Bard: эффективный аналог ChatGPT

В перечне популярных чат-ботов с искусственным интеллектом Google Bard (Gemini) еще не пользуется такой популярностью…

14.11.2024

Скрипт и программирование: что это такое простыми словами

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

12.11.2024

Дедлайн в разработке: что это такое простыми словами

Дедлайн (от англ. deadline — «крайний срок») — это конечная дата стачи проекта или задачи…

11.11.2024