Книга: Основы программирования в Linux

Одновременное выполнение

Одновременное выполнение

В упражнении 12.2 показано, как написать программу, которая проверяет одновременное выполнение двух потоков. (Вы, конечно, применяете однопроцессорную систему, ЦП будет искусно переключаться между потоками, а не одновременно выполнять оба потока, используя отдельные ядра процессора аппаратными средствами.) Поскольку вы не встречались еще с какими-либо функциями синхронизации потоков, это будет очень неэффективная программа, делающая нечто, именуемое опросом (polling) двух потоков. И снова вы воспользуетесь тем, что все, за исключением локальных переменных функции, совместно используется двумя потоками в процессе.

Упражнение 12.2. Одновременное выполнение двух потоков

Программа thread2.c в этом упражнении создается за счет небольших изменений программы thread1.c. Вы добавите дополнительную глобальную переменную для определения выполняющегося потока.

Примечание

Файлы с полными текстами примеров можно загрузить с Web-сайта книги.

int run_now = 1;

Задайте run_now равной 1, когда выполняется функция main, и 2, когда выполняется новый поток.

В функцию main после создания нового потока добавьте следующий код:

int print_count1 = 0;
while (print_count1+ < 20) {
 if (run_now == 1) {
  printf("1");
  run_now = 2;
 } else {
  sleep(1);
 }
}

Если переменная run_now равна 1, выведите "1" и присвойте переменной значение 2. В противном случае вы на короткое время засыпаете и снова проверяете значение. Вы ждете, пока значение изменится на 1, проверяя время от времени снова. Этот прием называется циклам активного или деятельного ожидания (busy wait), несмотря, на то, что в данном случае программа засыпает на секунду между очередными проверками. Позже в этой главе вы увидите, как сделать это лучше.

В функции thread_function, где выполняется ваш новый поток, вы делаете примерно то же самое, но с противоположными значениями.

int print_count2 = 0;
while (print_count2++ < 20) {
 if (run_now == 2) {
  printf("2");
  run_now = 1;
 } else {
  sleep(1);
 }
}

Вы удаляете переданные параметр и возвращаемое значение, т.к. они вас больше не интересуют.

Когда вы выполните программу, то увидите следующий вывод. (Вы можете обнаружить, что для формирования вывода, особенно на машине с одноядерным ЦП, программе потребуется несколько секунд.)

$ cc -D_REENTRANT thread2.с -о thread2 -lpthread
$ ./thread2
12121212121212121212
Waiting for thread to finish...
Thread joined

Как это работает

Каждый поток заставляет другой поток выполняться, задавая переменную run_now и затем ожидая, пока другой поток не изменит значение, чтобы можно было продолжить выполнение. Из программы видно, что выполнение переходит от одного потока к другому автоматическими кроме того, она демонстрирует точку, совместно используемую обоими потоками, — переменную run_now.

Оглавление книги


Генерация: 1.317. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз