Читать «Параллельное программирование на С++ в действии. Практика разработки многопоточных программ» онлайн - страница 18
Энтони Уильямс
}
Прежде всего, отметим наличие дополнительной директивы #include <thread>
(1). Все объявления, необходимые для поддержки многопоточности, помещены в новые заголовочные файлы; функции и классы для управления потоками объявлены в файле <thread>
, а те, что нужны для защиты разделяемых данных, — в других заголовках.
Далее, код вывода сообщения перемещен в отдельную функцию (2). Это объясняется тем, что в каждом потоке должна быть main()
, а для всех остальных задается в конструкторе объекта std::thread
. В данном случае в качестве начальной функции объекта типа std::thread
, названного t
(3), выступает функция hello()
.
Есть и еще одно отличие вместо того, чтобы сразу писать на стандартный вывод или вызывать hello()
из main()
, эта программа запускает новый поток, так что теперь общее число потоков равно двум: главный, с начальной функцией main()
, и дополнительный, начинающий работу в функции hello()
.
После запуска нового потока (3) начальный поток продолжает работать. Если бы он не ждал завершения нового потока, то просто дошел бы до конца main()
, после чего исполнение программы закончилась бы быть может, еще до того, как у нового потока появился шанс начать работу. Чтобы предотвратить такое развитие событие, мы добавили обращение к функции join()
(4); в главе 2 объясняется, что это заставляет вызывающий поток (main()
) ждать завершения потока, ассоциированного с объектом std::thread
, — в данном случае t
.
Если вам показалось, что для элементарного вывода сообщения на стандартный вывод работы слишком много, то так оно и есть, — в разделе 1.2.3 выше мы говорили, что обычно для решения такой простой задачи не имеет смысла создавать несколько потоков, особенно если главному потоку в это время нечего делать. Но далее мы встретимся с примерами, когда запуск нескольких потоков дает очевидный выигрыш.
1.5. Резюме
В этой главе мы говорили о том, что такое параллелизм и многопоточность и почему стоит (или не стоит) использовать их в программах. Мы также рассмотрели историю многопоточности в С++ — от полного отсутствия поддержки в стандарте 1998 года через различные платформенно-зависимые расширения к полноценной поддержке в новом стандарте С++11. Эта поддержка, появившаяся очень вовремя, дает программистам возможность воспользоваться преимуществами аппаратного параллелизма, которые стали доступны в современных процессорах, поскольку их производители пошли но пути наращивания мощности за счет реализации нескольких ядер, а не увеличения быстродействия одного ядра.
Мы также видели (пример в разделе 1.4), как просто использовать классы и функции из стандартной библиотеки С++. В С++ использование нескольких потоков само по себе несложно — сложно спроектировать программу так, чтобы она вела себя, как задумано.
Закусив примерами из раздела 1.4, пора приступить к чему-нибудь более питательному. В главе 1 мы рассмотрим классы и функции для управления потоками.