Page 83 - 4868
P. 83

81                                                               Ошибка! Стиль не определен.

                     arrive[i] = 1;
                     <await (continue[i] == 1);>

                     Процес  Coordinator  очікує,  поки  всі  елементи  масиву  arrive  не
               стануть  рівні  1,  а  потім  присвоює  значення  1  всім  елементам  масиву
               continue.

                     for [i = 1 to n] < await (arrive[i] == 1);>
                     for [i = 1 to n] continue[i] = 1;
                     Оператори await можна реалізувати  у вигляді циклів  while, оскільки
               кожен  із  них  посилається  лише  на  одну  спільну  змінну.  У  процесі

               Coordinator для очікування процедури присвоєння значень всім елементам
               arrive можна використати оператор for. Оскільки для продовження роботи
               процесів  Worker  повинні  бути  встановлені  значення  для  усіх  елементів
               масиву  arrive,  то  процес  Coordinator  може  перевіряти  їх  у  довільному
               порядку.  Конфліктів  звернення  до  пам’яті  тепер  не  буде,  оскільки  процеси
               очікують  зміни  різних  змінних,  кожна  з  яких  може  зберігатися  у  своєму
               рядку кеш-пам’яті.
                     Змінні  arrive  та  continue  в  представлених  програмах  є  прикладами
               так  званого  прапорця.  Його  встановлює  (піднімає)  один  процес,  щоб
               повідомити іншого про виконання умови синхронізації. Доповнимо програми
               кодом, який скидає прапорці (присвоюючи їм значення 0) для підготовки їх
               до  наступної  ітерації.  При  цьому  використовуються  два  основних  правила
               синхронізації за допомогою прапорців: 1) прапорець синхронізації скидається
               тільки  процесом,  який  очікує  його  установки;  2)  прапорець  не  можна
               встановлювати до тих пір, поки не відомо точно, що він скинутий.
                     Перше правило гарантує, що прапорець не буде скинутий, поки процес
               не визначить, що він  встановлений. Відповідно  з цим правилом, прапорець
               continue[і]  повинен  скидатися  процесом  Worker[і],  а  обнуляти  всі
               елементи  масиву  arrive  повинен  процес  Coordinator.  Згідно  з  другим
               правилом  процес  не  встановлює  прапорець  до  того  часу,  поки  він  не
               скинутий  іншим  процесом.  В  потилежному  випадку,  якщо  інший
               синхронізований  процес  очікує  повторної  установки  прапорця,  то  можлива
               ситуація  взаємного  блокування.  Це  означає,  що  процес  Coordinator
               повинен  скинути  значення  arrive[і]  перед  установкою  значення  змінної
               continue[і]. Процес Coordinator може зробити це, виконавши ще один
               оператор  for  після  першого  оператора  for.  Також  процес  Coordinator
               може скинути значення arrive[і] відразу після того, як дочекається його
               установки. Додавши код скидання прапорців, отримаємо бар’єр з керуючим
               процесом (лістинг 1.14).


                     Лістинг 1.14– Бар’єрна синхронізація з керуючим процесом
                     int arrive[1: n] = ([n] 0), continue[1: n] = ([n] 0);
                     process Worker[i = 1 to n] {
                       while (true) {
   78   79   80   81   82   83   84   85   86   87   88