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