Читаем C++. Сборник рецептов полностью

Она создает в стеке объект myThread, являющийся новым потоком операционной системы, который начинает выполнять функцию threadFun. В этот момент программный код функции threadFun и код функции main (по крайней мере, теоретически) выполняются параллельно. Конечно, на самом деле они могут выполняться не параллельно, поскольку ваша машина может иметь только один процессор, и в этом случае параллельная работа невозможна (благодаря недавно разработанным архитектурам процессоров это утверждение не совсем точное, но в настоящий момент я не буду принимать в расчет двухъядерные процессоры и т.п.). Если у вас только один процессор, то операционная система предоставит каждому созданному вами потоку квант времени в состоянии выполнения, перед тем как приостановить его работу. Так как эти кванты времени могут иметь различную величину, никогда нельзя с уверенностью сказать, какой из потоков раньше достигнет определенной точки. Именно в этой особенности многопоточного программирования заключается его сложность: состояние многопоточной программы недетерминировано. При выполнении несколько раз одной и той же многопоточной программы можно получить различные результаты. Темой рецепта 12.2 является координация ресурсов, используемых несколькими потоками.

После создания потока myThread поток main продолжает свою работу, по крайней мере на мгновение, пока не достигнет следующей строки.

boost::thread::yield();

Это переводит текущий поток (в данном случае поток main) в неактивное состояние, что означает переключение операционной системы на другой поток или процесс, используя некоторую политику, которая зависит от операционной системы. С помощью функции yield операционная система уведомляется о том, что текущий поток хочет уступить оставшуюся часть кванта времени. В это время новый поток выполняет threadFun. После завершения threadFun дочерний поток исчезает. Следует отметить, что объект thread не уничтожается, потому что он является объектом С++, который по-прежнему находится в области видимости. Эта особенность играет важную роль.

Объект потока — это некий объект, существующий в динамической памяти или в стеке и работающий подобно любому другому объекту С++. Когда программный код выходит из области видимости потока, все находящиеся в стеке объекты потока уничтожаются, или, с другой стороны, когда вызывающая программа выполняет оператор delete для thread*, исчезает соответствующий объект thread, который находится в динамической памяти. Но объекты thread выступают просто как прокси относительно реальных потоков операционной системы, и когда они уничтожаются, потоки операционной системы не обязательно исчезают. Они просто отсоединяются, что означает невозможность их подключения в будущем. Это не так уж плохо.

Потоки используют ресурсы, и в любом (хорошо спроектированном) многопоточном приложении управление доступом к таким ресурсам (к объектам, сокетам, файлам, «сырой» памяти и т.д.) осуществляется при помощи мьютексов, которые являются объектами, обеспечивающими последовательный доступ к каким-либо объектам со стороны нескольких потоков (см. рецепт 12.2). Если поток операционной системы оказывается «убитым», он не будет освобождать свои блокировки и свои ресурсы, подобно тому как «убитый» процесс не оставляет шансов на очистку буферов или правильное освобождение ресурсов операционной системы. Простое завершение потока в тот момент, когда вам кажется, что он должен быть завершен, — это все равно что убрать лестницу из-под маляра, когда время его работы закончилось.

Поэтому предусмотрена функция-член join. Как показано в примере 12.1, вы можете вызвать join, чтобы дождаться завершения работы дочернего потока, join — это вежливый способ уведомления потока, что вы собираетесь ждать завершения его работы.

myThread.join();

Поток, вызвавший функцию join, переходит в состояние ожидания, пока не закончит свою работу другой поток, представленный объектом myThread. Если он никогда не завершится, то никогда не завершится и join. Применение join — наилучший способ ожидания завершения работы дочернего потока.

Возможно, вы заметили, что, если передать что-либо осмысленное функции threadFun, но закомментировать join, поток не завершит свою работу. Вы можете убедиться в этом, выполняя в threadFun цикл или какую-нибудь продолжительную операцию. Это объясняется тем, что операционная система уничтожает процесс вместе со всеми его дочерними процессами независимо от того, закончили или нет они свою работу. Без вызова join функция main не будет ждать окончания работы своих дочерних потоков: она завершается, и поток операционной системы уничтожается.

Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных