Если в вашей системе по умолчанию установлена NPTL (что очень вероятно), почти наверняка вам не нужны опции -I
-L, и можно применить более простой вариант:$ cc -D_REENTRANT thread1.с -о thread1 -lpthread
В данной главе мы будем применять этот более простой вариант строки компиляции.
4. Когда вы выполните эту программу, то увидите следующие строки:
$ ./thread1
Waiting for thread to finish...
thread_function is running. Argument was Hello World
Thread joined, it returned Thank you for the CPU time
Message is now Bye!
Стоит потратить немного времени на анализ данной программы, поскольку мы будем использовать ее как основу в большинстве примеров этой главы.
Как это работает
Вы объявляете прототип функции, которую вызовет поток, когда вы его создадите:
void *thread_function(void *arg);
Как требует функция pthread_create
void и возвращает указатель на void. (Мы перейдем к реализации thread_function через минуту.)В функции main
pthread_create, чтобы начать выполнение нового потока.pthread_t a_thread;
void *thread_result;
res = pthread_create(&a_thread, NULL, thread_function, (void *)message);
Вы передаете адрес объекта типа pthread_t
NULL. Последние два параметра — вызываемая функция и передаваемый ей параметр.Если вызов завершился нормально, теперь выполняются два потока. Исходный поток (main
pthread_create, а новый поток начинает выполнение в функции, образно названной thread_function.Исходный поток проверяет, запустился ли новый поток, и затем вызывает функцию pthread_join
res = pthread_join(a_thread, &thread_result);
Здесь вы передаете идентификатор потока, который ждете, чтобы присоединить, и указатель на результат. Эта функция, прежде чем вернуть управление, будет ждать, пока другой поток не завершится. Затем она выводит возвращаемое из потока значение и содержимое переменной и завершается.
Новый поток начинает выполнение, запуская функцию thread_function
main. Новый поток пишет в тот же массив message, к которому у исходного потока есть доступ. Если бы вы вызвали функцию fork вместо pthread_create, массив представлял бы собой копию массива message, а не сам массив.Одновременное выполнение
В упражнении 12.2 показано, как написать программу, которая проверяет одновременное выполнение двух потоков. (Вы, конечно, применяете однопроцессорную систему, ЦП будет искусно переключаться между потоками, а не одновременно выполнять оба потока, используя отдельные ядра процессора аппаратными средствами.) Поскольку вы не встречались еще с какими-либо функциями синхронизации потоков, это будет очень неэффективная программа, делающая нечто, именуемое
Программа thread2.c в этом упражнении создается за счет небольших изменений программы thread1.c. Вы добавите дополнительную глобальную переменную для определения выполняющегося потока.
Файлы с полными текстами примеров можно загрузить с Web-сайта книги.
int run_now = 1;
Задайте run_now
main, и 2, когда выполняется новый поток.В функцию main
int print_count1 = 0;
while (print_count1+ < 20) {
if (run_now == 1) {
printf("1");
run_now = 2;
} else {
sleep(1);
}
}