Операционные системы. Управление ресурсами




. Примитивы синхронизации в языках программирования


До сих пор мы рассматривали методы, которые обеспечивают и взаимное исключение, и синхронизацию. Целый ряд прикладных задач, однако, требует только синхронизации без взаимного исключения. Отказ от последнего, если это не мешает решению задачи, всегда оправдан, так как взаимное исключение усложняет решение может снижать уровень мультипрограммирования.

Один из возможных примитивов, обеспечивающих синхронизацию без взаимного исключения, называется счетчиком событий. Счетчик событий - тип данных, представляемый неуменьшающимся целым числом с начальным значением 0. Его значение в любой момент времени - число событий определенного типа, произошедших от некоторой точки начала отсчета. Над этим типом данных возможны следующие операции:

  • advance(E) - увеличение значения счетчика событий E на 1, атомарная операция;
  • eread(E) - возвращает текущее значение счетчика E, эта операция не взаимоисключающая с advance, так что к моменту, когда значение попадет в читающий его процесс, текущее значение счетчика может быть уже изменено;
  • await(E,value) - ждать - ожидание (блокировка процесса), пока значение счетчика E не станет большим или равным value.

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

Вот как решается с помощью счетчиков событий задача для одного производителя и одного потребителя:

1 typedef unsigned int eventcounter; /* тип данных - счетчик событий */ 2 static eventcounter inCnt = 0, outCnt = 0; /* счетчики для чтения и записи */ 3 static portion buffer [BUFSIZE]; /* буфер */ 4 /*== процесс-потребитель ==*/ 5 void consumer ( void ) { 6 int portNum; /* номер порции */ 7 portion work; /* рабочая область порции */ 8 /* цикл потребления */ 9 for ( portNum = 1; ; portNum++ ) { 10 /* ожидание доступности порции по номеру */ 11 await (inCnt, portNum); 12 /* выборка из буфера */ 13 memcpy (&work, buffer + portNum % BSIZE, sizeof(portion) ); 14 /* продвижение счетчика записи */ 15 advance (outCnt); 16 < обработка порции в work > 17 } 18 } 19 /*== процесс-производитель ==*/ 20 void producer ( void ) { 21 int portNum; /* номер порции */ 22 portion work; /* рабочая область для порции */ 23 /* цикл производства */ 24 for ( portNum = 1; ; portNum++ ) { 25 < производство порции в work > 26 /* ожидание доступности порции по номеру */ 27 await (outCnt, portNum - BSIZE); 28 /* запись в буфер */ 29 memcpy (buffer + portNum % BSIZE, &work, sizeof(portion) ); 30 /* продвижение счетчика чтения */ 31 advance (inCnt); 32 } 33 }




Содержание  Назад  Вперед