Page 92 - 6571
P. 92

ґрунтується на витягуванні квитків (номерів) і подальшого очіку-
                  вання своєї черги (лістинг 10).



                        Лістинг 10 – Алгоритм квитка (крупномодульне рішення)
                        int number = 1, next = 1, turn[1: n] = ([n] 0);

                        process CS[i = 1 to n] {
                          while (true) {
                            <turn[i] = number;
                            number = number+1;>
                            < await(turn[i] == next);>
                              критична секція;
                            <next = next+1;>
                            некритична секція;
                          }
                        }

                        Нехай number та next – цілочисельні змінні з початковими
                  значеннями 1, a turn[1: n] – масив цілих чисел з початковими

                  значеннями  0.  Щоб  увійти  в  критичну  секцію,  процес  CS[i]
                  спочатку присвоює елементу turn[i] поточне значення number
                  і  збільшує  значення  number  на  1.  Для  того  щоб  процеси

                  (відвідувачі)  отримували  унікальні  номери,  ці  дії  повинні
                  виконуватися  неподільним  чином.  Після  цього  процес  CS[i]

                  очікує, поки значення змінної next не стане рівним номеру, який
                  вони  отримали.  При  завершенні  критичної  секції  процес  CS[i]
                  знову в неподільній дії збільшує на 1 значення next.
                        На відміну від алгоритму розриву вузла, алгоритм квитка має

                  потенційний           недолік,        загальний          для      алгоритмів,          що
                  використовують  нарощення  лічильника:  значення  number  та

                  next  необмежені.  Якщо  алгоритм  квитка  виконувати  досить
                  довго,  то  збільшення  лічильників  призведе  до  арифметичного
                  переповнення.  Однак  на  практиці  це  малоймовірно  і  не  є
                  суттєвою проблемою.

                        Алгоритм  в  лістингу  10  містить  три  крупномодульні  дії.
                  Оператор  await  легко  реалізується  циклом  з  активним

                  очікуванням, оскільки в булевому виразі використана тільки одна
                  спільна змінна. Останню неподільну дію, що виконує збільшення
                  змінної  next,  можна  реалізувати  за  допомогою  звичайних
                  інструкцій  завантаження  і  збереження,  оскільки  в  будь-який

                                                              91
   87   88   89   90   91   92   93   94   95   96   97