У поточно-локальных переменных есть и другие общие черты со статическими переменными — они инициализируются нулями перед последующей инициализацией (например, динамической) и, если конструктор поточно-локальной переменной возбуждает исключение, то вызывается функция std::terminate()
, которая аварийно завершает приложение.
Деструкторы всех поточно-локальных переменных, сконструированных в данном потоке, вызываются после возврата из функции потока в порядке, обратном конструированию. Поскольку порядок инициализации не определён, то необходимо гарантировать отсутствие взаимозависимостей между деструкторами таких переменных. Если деструктор поточно-локальной переменной возбуждает исключение, то вызывается функция std::terminate()
, как и при конструировании.
Поточно-локальные переменные, принадлежащие некоторому потоку, уничтожаются также в случае, когда данный поток вызывает std::exit()
или возвращается из main()
(что эквивалентно вызову std::exit()
со значением, которое вернула main()
). Если другие потоки продолжают работать, когда приложение завершается, то деструкторы принадлежащих им поточно-локальных переменных не вызываются.
Хотя поточно-локальные переменные, принадлежащие разным потокам, имеют разные адреса, все же можно получать обычный указатель на такую переменную. Этот указатель адресует объект в том потоке, где указатель был получен, и, следовательно, его можно использовать для предоставления доступа к этому объекту из других потоков. Попытка доступа к уже уничтоженному объекту является неопределенным поведением (как всегда), потому, передавая указатель на поточно-локальную переменную в другой поток, следите за тем, чтобы он не разыменовывался после завершения потока-владельца.
В этом приложении мы смогли лишь пробежаться по верхам новых языковых средств, появившихся в стандарте C++11, поскольку нас интересовали лишь те возможности, которые активно используются в библиотеке Thread Library. Из других средств стоит отметить статические утверждения, строго типизированные перечисления, делегирующие конструкторы, поддержку Unicode, псевдонимы шаблонов, новую универсальную последовательность инициализации, а также ряд других, более мелких изменений. Подробное описание всех новых средств выходит далеко за рамки этой книги и, пожалуй, заслуживает отдельного тома. Лучший из существующих на данный момент обзор всего множества изменений, наверное, приведён в FAQ'e по C++11 [21] http://www.research.att.com/~bs/C++0xFAQ.html
Бьярна Страуструпа, хотя популярные учебники по С++ в скором времени, вероятно, будут переизданы с учетом всех новшеств.
Я надеюсь, что в этом кратком введении в новые языковые средства мне все же удалось объяснить, как они соотносятся с библиотекой Thread Library, и что с его помощью вы сможете писать и понимать многопоточный код, в котором эти средства используются. Но не забывайте, что это отнюдь не полный справочник и не учебник по использованию новых возможностей языка. Если вы намерены активно пользоваться ими, то рекомендую приобрести достаточно подробную книгу, которая позволит задействовать их в полной мере.
Приложение В.
Краткое сравнение библиотек для написания параллельных программ
Поддержка параллелизма и многопоточности в языках программирования и библиотеках не является чем-то новым, хотя включение ее в стандарт С++ — действительно новшество. Например, в Java многопоточность поддерживалась уже в самой первой версии; на платформах, согласованных со стандартом POSIX, имеется интерфейс из языка С к средствам многопоточности, предоставляемым операционной системой, а язык Erlang поддерживает параллелизм на основе передачи сообщений. Существуют даже библиотеки классов для С++, например Boost, которые обертывают программный интерфейс к средствам многопоточности, существующим на данной платформе (будь то интерфейс POSIX С или нечто иное) и тем самым предоставляют переносимый интерфейс для всех поддерживаемых платформ.
Для тех, кто уже имеет опыт написания многопоточных приложений и хотел бы воспользоваться им для разработки программ на С++ с применением новых возможностей, в этом приложении проводится сравнение средств, имеющихся в Java, POSIX С, С++ с библиотекой Boost Thread Library и С++11. Даются также перекрестные ссылки на соответствующие главы этой книги.
Средство |
Java |
Posix C |
Boost Threads |
C++11 |
Глава |
Запуск потоков |
Класс java.lang.thread |
Тип pthread_t и соответствующие функции API: pthread_create() , pthread_detach() , pthread_join() |
Класс boost::thread и его функции-члены |
Класс std::thread и его функции-члены |
Глава 2 |
Взаимное исключение |
Блоки synchronized |
Тип pthread_mutex_t и соответствующие функции API: pthread_mutex_lock() , pthread_mutex_unlock() и другие |
Класс boost::mutex и его функции-члены, шаблоны boost::lock_guard<> и boost::unique_lock<> |
Класс std::mutex и его функции-члены, шаблоны std::lock_guard<> и std::unique_lock<> |
Глава 3 |
Ожидание предиката |
Методы wait() и notify() класса java.lang.Object , используемые внутри блоков synchronized |
Тип pthread_cond_t и соответствующие функции API: pthread_cond_wait() , pthread_cond_timed_wait() и другие |
Классы boost::condition_variable и boost::condition_variable_any и их функции-члены |
Классы std::condition_variable и std::condition_variable_any и их функции-члены |
Глава 4 |
Атомарные операции и модель памяти с учетом параллелизма |
volatile -переменные, типы в пакете java.util.concurrent.atomic |
Отсутствует |
Отсутствует |
Типы std::atomic_xxx , шаблон класса std::atomic<> , функция std::atomic_thread_fence() |
Глава 5 |
Потокобезопасные контейнеры |
Контейнеры в пакете java.util.concurrent . |
Отсутствует |
Отсутствует |
Отсутствует |
Главы 6 и 7 |
Будущие результаты |
Интерфейс java.util.concurrent.future и ассоциированные с ним классы |
Отсутствует |
Шаблонные классы boost::unique_future<> и boost::shared_future<> |
Шаблонные классы std::future<> , std::shared_future<> , и std::atomic_future<> |
Глава 9 |
Пулы потоков |
Класс java.util.concurrent.ThreadPoolExecutor |
Отсутствует |
Отсутствует |
Отсутствует |
Глава 9 |
Прерывание потока |
Метод interrupt() класса java.lang.Thread |
pthread_cancel() |
Функция-член interrupt() класса boost::thread |
Отсутствует |
|
Читать дальше