barrier_wait(&barrier);
// После этого момента все потоки уже завершатся
time(&now);
printf("Барьер в потоке 1, время срабатывания %s",
ctime_r(&now, buf));
}
void* thread2(void *not_used) {
time_t now;
char buf[27];
time(&now);
printf("Поток 2, время старта %s", ctime_r(&now, buf));
// Выполнить вычисления
// (вместо этого просто сделаем sleep)
sleep(40);
barrier_wait(&barrier);
// После этого момента все потоки уже завершатся
time(&now);
printf("Барьер в потоке 2, время срабатывания %s",
ctime_r(&now, buf));
}
main() // Игнорировать аргументы
{
time_t now;
char buf[27];
// Создать барьер со значением счетчика 3
barrier_init(&barrier, NULL, 3);
// Создать два потока, thread1 и thread2
pthread_create(NULL, NULL, thread1, NULL);
pthread_create(NULL, NULL, thread2, NULL);
// Сейчас выполняются оба потока
// Ждать завершения
time(&now);
printf("main(): ожидание у барьера, время %s",
ctime_r(&now, buf));
barrier_wait(&barrier);
// После этого момента все потоки уже завершатся
time(&now);
printf("Барьер в main(), время срабатывания %s",
ctime_r(&now, buf));
}
Основной поток создал объект типа «барьер» и инициализировал его значением счетчика, равным числу потоков (включая себя!), которые должны «встретиться» у барьера, прежде чем он «прорвется». В нашем примере этот индекс был равен 3 — один для потока sleep(20)
и sleep(40)
, чтобы имитировать вычисления. Для осуществления синхронизации основной поток (
Как упоминалось ранее, с функцией
Предположим, что мы слегка изменили наш пример так, чтобы можно было проиллюстрировать, почему иногда хорошо иметь несколько потоков даже в системе с одиночным процессором.
В таком модифицированном примере один узел на сети ответственен за вычисление строк растра (как и в примере с графикой, рассмотренном выше). Однако, когда строка рассчитана, ее данные должны быть отправлены по сети другому узлу, который выполняет функцию отображения. Ниже приведена соответствующая модифицированная функция
int main(int argc, char **argv) {
int x1;
... // выполнить инициализации
for (x1 = 0; x1 < num_x_lines; x1++) {
do _one_line(x1); // Область «С» на схеме
tx_one_line_wait_ack(x1); // Области «X» и «W» на схеме
}
}