Чтение онлайн

на главную - закладки

Жанры

Программирование для Linux. Профессиональный подход

Самьюэл Алекс

Шрифт:

PARAMETERS является указателем на структуру char_print_parms. */

void* char_print(void* parameters) {

 /* Приведение указателя к нужному типу. */

 struct char_print_parms* p =

(struct char_print_parms*)parameters;

 int i;

 for (i = 0; i < p->count; ++i)

fputc(p->character, stderr);

 return NULL;

}

/*
Основная программа. */

int main {

 pthread_t thread1_id;

 pthread_t thread2_id;

 struct char_print_parms thread1_args;

 struct char_print_parms thread2_args;

 /* Создание нового потока, отображающего 30000

символов 'x'. */

 thread1_args.character = 'x';

 thread1_args.count = 30000;

 pthread_create(&thread1_id, NULL, &char_print, &thread1_args);

 /* Создание нового потока, отображающего 20000

символов 'o'. */

 thread2_args.character = 'o';

 thread2_args.count = 20000;

 pthread_create(&thread2_id, NULL, &char_print, &thread2_args);

 return 0;

}

Но постойте! Приведенная программа имеет серьезную ошибку. Основной поток (выполняющий функцию

main
) создает структуры
thread1_args
и
thread2_args
в виде локальных переменных, а затем передает указатели на них дочерним потокам. Что мешает Linux распланировать работу потоков так, чтобы функция
main
завершилась до того, как будут завершены другие два потока? Ничего! Но если это произойдет, структуры окажутся удаленными из памяти, хотя оба потока все еще ссылаются на них.

4.1.2. Ожидание завершения потоков

Одно из решений описанной выше проблемы заключается в том, чтобы заставить функцию

main
дождаться завершения обоих потоков. Нужна лишь функция наподобие
wait
, которая работает не с процессами, а с потоками. Такая функция называется
pthread_join
. Она принимает два аргумента: идентификатор ожидаемого потока и указатель на переменную
void*
, в которую будет записано значение, возвращаемое потоком. Если последнее не важно, задайте в качестве второго аргумента
NULL
.

В листинге 4.3 приведена исправленная версия функции

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

Листинг 4.3. Исправленная функция
main
из файла thread-create.c

int main {

 pthread_t thread1_id;

 pthread_t thread2_id;

 struct char_print_parms thread1_args;

 struct char_print_parms thread2_args;

 /*
Создание нового потока, отображающего 30000

символов 'x'. */

 thread1_args.character = 'x';

 thread1_args.count = 30000;

 pthread_create(&thread1_id, NULL, &char_print, &thread1_args);

 /* Создание нового потока, отображающего

20000 символов 'o'. */

 thread2_args.character = 'o';

 thread2_args.count = 20000;

 pthread_create(&thread2_id, NULL, &char_print, &thread2_args);

 /* Убеждаемся, что завершился первый поток. */

 pthread_join(thread1_id, NULL);

 /* Убеждаемся, что завершился второй поток. */

 pthread_join(thread2_id, NULL);

 /* Теперь можно спокойно завершать работу. */

 return 0;

}

Мораль сей басни такова: убедитесь, что любые данные, переданные потоку по ссылке, не удаляются (даже другим потоком) до тех пор, пока поток не завершит свою работу с ними. Это относится как к локальным переменным, удаляемым автоматически при выходе за пределы своей области видимости, так и к динамическим переменным, удаляемым с помощью функции

free
(или оператора
delete
в C++).

4.1.3. Значения, возвращаемые потоками

Если второй аргумент функции

pthread_join
не равен NULL, то в него помещается значение, возвращаемое потоком. Как и потоковый аргумент, это значение имеет тип
void*
. Если поток возвращает обычное число типа
int
, его можно свободно привести к типу
void*
, а затем выполнить обратное преобразование по завершении функции
pthread_join
. [13]

13

Данный способ не является стандартным. В обязанности программиста входит убедиться, что в процессе подобных преобразований не произойдет потеря значащих разрядов.

Программа, представленная в листинге 4.4, в отдельном потоке вычисляет n– е простое число и возвращает его в программу. Тем временем функция

main
может продолжать свои собственные вычисления. Сразу признаемся: алгоритм последовательного деления, используемый в функции
compute_prime
, весьма неэффективен. В книгах по численным методам описаны более мощные алгоритмы (например, "решето Эратосфена").

Листинг 4.4. (primes.с) Вычисление простых чисел в потоке
Поделиться:
Популярные книги

Инцел на службе демоницы 1 и 2: Секса будет много

Блум М.
Инцел на службе демоницы
Фантастика:
фэнтези
5.25
рейтинг книги
Инцел на службе демоницы 1 и 2: Секса будет много

Весь цикл «Десантник на престоле». Шесть книг

Ланцов Михаил Алексеевич
Десантник на престоле
Фантастика:
альтернативная история
8.38
рейтинг книги
Весь цикл «Десантник на престоле». Шесть книг

Предатель. Цена ошибки

Кучер Ая
Измена
Любовные романы:
современные любовные романы
5.75
рейтинг книги
Предатель. Цена ошибки

Жандарм 2

Семин Никита
2. Жандарм
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Жандарм 2

Прогрессор поневоле

Распопов Дмитрий Викторович
2. Фараон
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Прогрессор поневоле

Всемирная энциклопедия афоризмов. Собрание мудрости всех народов и времен

Агеева Елена А.
Документальная литература:
публицистика
5.40
рейтинг книги
Всемирная энциклопедия афоризмов. Собрание мудрости всех народов и времен

Истребитель. Ас из будущего

Корчевский Юрий Григорьевич
Фантастика:
боевая фантастика
попаданцы
альтернативная история
5.25
рейтинг книги
Истребитель. Ас из будущего

Очешуеть! Я - жена дракона?!

Амеличева Елена
Фантастика:
юмористическая фантастика
5.43
рейтинг книги
Очешуеть! Я - жена дракона?!

Отмороженный 4.0

Гарцевич Евгений Александрович
4. Отмороженный
Фантастика:
боевая фантастика
постапокалипсис
рпг
5.00
рейтинг книги
Отмороженный 4.0

Треугольная шляпа. Пепита Хименес. Донья Перфекта. Кровь и песок.

Бласко Висенте Ибаньес
65. Библиотека всемирной литературы
Проза:
классическая проза
5.00
рейтинг книги
Треугольная шляпа.
Пепита Хименес.
Донья Перфекта.
Кровь и песок.

Измена. Жизнь заново

Верди Алиса
1. Измены
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Измена. Жизнь заново

Три `Д` для миллиардера. Свадебный салон

Тоцка Тала
Любовные романы:
современные любовные романы
короткие любовные романы
7.14
рейтинг книги
Три `Д` для миллиардера. Свадебный салон

Бастард Императора. Том 5

Орлов Андрей Юрьевич
5. Бастард Императора
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Бастард Императора. Том 5

Идеальный мир для Лекаря 21

Сапфир Олег
21. Лекарь
Фантастика:
фэнтези
юмористическое фэнтези
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 21