Page 160 - 6571
P. 160

sums[myid] = total;
                          Barrier();
                          if (myid == 0) {
                            /* процес з індексом 0 обчислює загальну суму */

                            total = 0;
                            for (i = 0; i < numWorkers; i++)
                              total += sums[i];
                            printf("Сума дорівнює %d\n", total);
                          }
                        }

                        Цілочисельні  змінні  та  функція  Barrier  на  початку
                  лістингу2.2  реалізують  повторно  використовуваний  бар’єр-

                  лічильник. Вони не включені в оголошення монітора, але ведуть
                  себе  так,  ніби  знаходяться  в  моніторі.  Тіло  функції  Barrier
                  починається  блокуванням  м’ютекса  і  закінчується  його
                  звільненням. Усередині функції процеси, які першими підійдуть

                  до бар’єра, очікують встановлення відповідного значення змінній
                  go,  після  чого  скидають  блокування  монітора.  Робочий  процес,
                  що  підійшов  до  бар’єра  останнім,  заново  ініціалізує  (обнуляє)

                  змінну numArrived і запускає інші робочі процеси за допомогою
                  відповідного           примітиву           оповіщення.           Робочі         процеси
                  виконуються по одному, при цьому утримуючи м’ютекс. Кожен з

                  них  після  свого  завершення  знімає  блокування  з  м’ютекса  і
                  виконує вихід з функції Barrier.
                        У функції main виконується ініціалізація спільних змінних і

                  створюються  відповідні  потоки.  Останній  аргумент  функції
                  pthread_create  використовується  для  передачі  потоку
                  унікального  ідентифікатора.  Функція  main  закінчує  своє

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

                  рядка  матриці  і  записує  результат  у  відповідний  елемент
                  глобального  масиву  sums.  Використання  масиву  (а  не  окремої
                  змінної),  дозволяє  уникнути  появи  критичних  секцій.  Коли  всі

                  робочі  процеси  підходять  до  точки  бар’єрної  синхронізації,  то
                  робочий процес з індексом 0 обчислює та виводить на друк суму
                  всіх елементів матриці.


                        Запитання для самоперевірки


                                                             159
   155   156   157   158   159   160   161   162   163   164   165