Семафор — специальный объект операционной системы, над которым определены две базовые операции: операция закрытия и операция открытия. Семафорный объект может быть доступен одновременно нескольким процессам (это обеспечивается операционной системой) и в этом смысле он представляет собой разделяемый ресурс.
Основой семафора является семафорная переменная S, которая в случае простейшего (двоичного) семафора может принимать значения 0 или 1. Значение 0 соответствует "закрытому" состоянию семафора, значение 1 — "открытому". Операции закрытия и открытия семафора изменяют значение семафорной переменной.
Действия, выполняемые операцией закрытия семафора:
  1. Проверить значение семафорной переменной S.
  2. Если S=1 (семафор открыт), присвоить S значение 0 ("закрыть" семафор).
  3. Если S=0 (семафор уже закрыт), перевести процесс, пытающийся закрыть семафор, в состояние ожидания (состояние блокировки).
Действия, выполняемые операцией открытия семафора:
  1. Если в списке заблокированных процессов находится процесс, ожидающий открытия данного семафора, перевести этот процесс в состояние готовности.
  2. Если в списке заблокированных процессов нет процесса, ожидающего открытия данного семафора, присвоить S значение 1 ("открыть" семафор)
Так как семафор доступен одновременно нескольким процессам, возможна ситуация, когда несколько процессов одновременно попытаются выполнить операцию открытия или закрытия. Чтобы этого избежать, операции открытия и закрытия семафора защищаются от одновременного вызова несколькими процессами на уровне операционной системы. Для этого на время выполнения указанных операций в ОС отключается передиспетчеризация процессов. Так как операции открытия и закрытия семафора являются короткими и выполняются за ограниченное малое время, такое временное отключение диспетчеризации не вызывает сколь-нибудь серьезных проблем.
Как же используются семафоры? Посмотрим на следующий пример. Пусть Sem — объект типа "семафор", предоставленный операционной системой. Sem.Open — операция открытия семафора, Sem.Close — операция закрытия.
Пример 1
Program 6;
procedure Proc1;
  begin
  While True do        {Бесконечный цикл, выполняемый в процессе}
    begin
      Sem.Close;       {Закрытие семафора}
      CrBlock1;        {Критический блок}
      Sem.Open;        {Открытие семафора}
...................    {Другие операции процесса, не входящие в КУ}
    end;
  end;
procedure Proc2;
  begin
  While True do        {Бесконечный цикл, выполняемый в процессе}
    begin
      Sem.Close;       {Закрытие семафора}
      CrBlock2;        {Критический блок}
      Sem.Open;        {Открытие семафора}
...................    {Другие операции процесса, не входящие в КУ}
    end;
  end;
begin
  Par_begin       {Запуск параллельных процессов}
   Proc1;
   Proc2;
  Par_end;
end.
Как видно, техника использования семафоров предельно проста. Перед входом в КУ процесс закрывает семафор. При этом все другие процессы "засыпают" на закрытом семафоре при входе в свои КУ. После выхода из КУ процесс открывает семафор, давая возможность "заснувшим на входе" процессам войти в свои КУ.
Таким образом, использование семафора является простой и удобной техникой синхронизации асинхронных процессов. Как видно, прим. 1 содержит минимум кода, обеспечивающего собственно синхронизацию, так как основная работа выполняется операционной системой.