logo search
Языки программирования

12.4. Мониторы и защищенные переменные

Проблема, связанная с семафорами и аналогичными средствами, обеспечи­ваемыми операционной системой, состоит в том, что они не структурны. Ес­ли нарушено соответствие между Wait и Signal, программа может утратить синхронизацию или блокировку. Для решения проблемы структурности была разработана концепция так называемых мониторов (monitors), и они реализованы в нескольких языках. Монитор — это совокупность данных и подпрограмм, которые обладают следующими свойствами:

• Данные доступны только подпрограммам монитора.

• В любой момент времени может выполняться не более одной подпро­граммы монитора. Попытка процесса вызвать процедуру монитора в то время, как другой процесс уже выполняется в мониторе, приведет к при­остановке нового процесса.

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

Первоначально модель параллелизма в языке Ada (описанная ниже в раз­деле 12.7) была чрезвычайно сложной и требовала слишком больших затрат для решения простых проблем взаимных исключений. Чтобы это исправить, в Ada 95 были введены средства, аналогичные мониторам, которые называ­ются защищенными переменными (protected variables). Например, семафор можно смоделировать как защищенную переменную. Этот интерфейс опре­деляет две операции, но целочисленное значение семафора рассматривает как приватное (private), что означает, что оно недоступно для пользователей семафора:

protected type Semaphore is

entry Wait;

procedure Signal;

private

Value: Integer := 1;

end Semaphore;

Реализация семафора выглядит следующим образом:

protected body Semaphore is

entry Wait when Value > 0 is

begin

Ada

Value := Value- 1;

end Wait;

procedure Signal is

begin

Value := Value + 1 ;

end Signal;

end Semaphore;

Выполнение entry и procedure взаимно исключено: в любой момент времени только одна задача будет выполнять операцию с защищенной переменной. К тому же entry имеет барьер (barrier), который является булевым выражением. Задача, пытающаяся выполнить entry, будет заблокирована, если выражение имеет значение «ложь». Всякий раз при завершении защищенной операции все барьеры будут перевычисляться, и будет разрешено выполнение той зада­чи, барьер которой имеет значение «истина». В приведенном примере, когда Signal увеличит Value, барьер в Wait будет иметь значение «истина», и забло­кированная задача сможет выполнить тело entry.