Основы программирования в Linux
Шрифт:
Как это работает
На сей раз вы создаете массив идентификаторов потоков:
pthread_t a_thread[NUM_THREADS];
и заключаете в цикл создание нескольких потоков:
for (lots_of_threads = 0; lots_of_threads < NUM_THREADS; lots_of_threads++) {
res = pthread_create(&(a_thread[lots_of_threads]), NULL,
thread_function, (void *)&lots_of_threads);
if (res != 0) {
perror("Thread creation failed");
exit(EXIT_FAILURE);
}
sleep(1);
}
Затем потоки сами по себе ждут в течение случайного промежутка времени, прежде чем начать выполнение:
void *thread_function(void *arg) {
int my_number = *(int *)arg;
int rand_num;
printf("thread_function is running. Argument was %d\n", my_number);
rand_num = 1+(int)(9.0* rand/(RAND_MAX+1.0));
sleep(randnum);
printf("Bye from %d\n", my_number);
pthread_exit(NULL);
}
В это время в основном (исходном) потоке вы ждете, чтобы собрать потоки, но не в том порядке, в каком вы их создали:
for (lots_of_threads = NUM_THREADS - 1; lots_of_threads >= 0; lots_of_threads--) {
res = pthread_join(a_thread[lots_of__threads], &thread_result);
if (res == 0) {
printf("Picked up a thread\n");
} else {
perror("pthread_join failed");
}
}
Если вы попробуете выполнить программу без вызова
sleep
, то увидите странный эффект: некоторые потоки запускаются с одним и тем же номером, например, вы можете получить вывод, похожий на следующий:
thread_function is running. Argument was 0
thread_function is running. Argument was 2
thread_function is running. Argument was 2
thread_function is running. Argument was 4
thread_function is running. Argument was 4
thread_function is running. Argument was 5
Waiting for threads to finish...
Bye from 5
Picked up a thread
Bye from 2
Bye from 0
Bye from 2
Bye from 4
Bye from 4
Picked up a thread
Picked up a thread
Picked up a thread
Picked up a thread
Picked up a thread
All done
Вы догадались, что произошло? Потоки запускаются, используя локальную переменную как аргумент функции потока. Эта переменная обновляется в цикле. Далее приведены ошибочные строки:
for (lots_of_threads = 0; lots_of_threads < NUM_THREADS; lots_of_threads++) {
res = pthread_create(&(a_thread[lots_of_threads]), NULL,
thread_function, (void *)&lots_of_threads);
Если поток
main
выполняется достаточно быстро, он может искажать аргумент (lots_of_threads
) для некоторых потоков. Поведение, подобное этому, наблюдается, когда недостаточно внимания уделяется совместно используемым переменным и множественным путям исполнения (multiple execution paths). Мы предупреждали вас о том, что программирование потоков требует повышенного внимания при разработке! Для исправления ошибки вам следует передавать непосредственно значение следующим образом:
res = pthread_create(&(a_thread[lots_of_threads]), NULL,
thread_function, (void *)lots_of_threads);
и конечно изменить
thread_function
:
void *thread_function(void *arg) {
int my_number = (int)arg;
Все исправления, выделенные цветом, показаны в программе thread8a.c.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#define NUM_THREADS 6
void *thread_function(void *arg);
int main {
int res;
pthread_t a_thread[NUM_THREADS];
void *thread_result;
int lots_of_threads;
for (lots_of_threads = 0; lots_of_threads < NUM_THREADS; lots_of_threads++) {
res = pthread_create(&(a_thread[lots_of_thread]), NULL,
thread_function, (void*)lots_оf_threads);
if (res != 0) {
perror("Thread creation failed");
exit(EXIT_FAILURE);
}
}
printf("Waiting for threads to finish...\n");
Поделиться:
Популярные книги
Первый среди равных. Книга X
10. Первый среди Равных
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Мастер порталов
8. Гибрид
Фантастика:
боевая фантастика
попаданцы
технофэнтези
аниме
фэнтези
5.00
рейтинг книги
Шайтан Иван 6
6. Шайтан Иван
Фантастика:
попаданцы
альтернативная история
историческое фэнтези
7.00
рейтинг книги
Моров. Том 3
2. Моров
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я до сих пор не князь. Книга XVI
16. Дорогой барон!
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Вернувшийся: Посол. Том IV
4. Вернувшийся
Фантастика:
космическая фантастика
киберпанк
5.00
рейтинг книги
На границе империй. Том 7
7. Фортуна дама переменчивая
Фантастика:
боевая фантастика
космическая фантастика
попаданцы
6.75
рейтинг книги
Хозяин оков V
5. Хозяин Оков
Фантастика:
фэнтези
попаданцы
гаремник
5.00
рейтинг книги
Петля, Кадетский корпус. Книга первая
1. Петля
Фантастика:
боевая фантастика
попаданцы
аниме
6.11
рейтинг книги
Мое ускорение
5. Девяностые
Фантастика:
попаданцы
альтернативная история
6.33
рейтинг книги
Кодекс Охотника. Книга XXXVIII
38. Кодекс Охотника
Фантастика:
фэнтези
боевая фантастика
попаданцы
юмористическое фэнтези
5.00
рейтинг книги
Истребители. Трилогия
Фантастика:
альтернативная история
7.30
рейтинг книги
Я царь. Книга XXVIII
28. Дорогой барон!
Фантастика:
боевая фантастика
аниме
попаданцы
5.00
рейтинг книги
Воплощение Похоти
1. Воплощение Похоти
Фантастика:
юмористическое фэнтези
попаданцы
рпг
аниме
5.00