Именно по этой причине нельзя рассматривать данную главу как введение в многопоточное программирование. Если вы уже имели опыт многопоточного программирования, но не на C++ или без использования библиотеки Boost Threads, эта глава будет полезна для вас. Однако описание основных принципов многопоточного программирования выходит за рамки этой книги. Если до сих пор вы никогда не занимались многопоточным программированием, по-видимому, вам следует прочитать вводный материал по этой тематике, но такой материал трудно найти, потому что большинство программистов не используют потоки выполнения (хотя, возможно, их и следовало бы применить).
Большая часть документации Boost и некоторые приводимые ниже рецепты при обсуждении классов используют понятия mutex
в библиотеке Boost Threads. ReadWriteMutex
, т.е. мьютекс с некоторыми дополнительными возможностями.
Наконец, потоки делают что-то одно из трех: работают, находятся в ожидании чего-то или готовы начать работу, но ничего не ожидают и не выполняют никаких действий. Эти состояния носят названия состояний
12.1. Создание потока
Требуется создать поток (thread) для выполнения некоторой задачи, в то время как главный поток продолжает свою работу.
Создайте объект класса thread
и передайте ему функтор, который выполняет данную работу. Создание объекта потока приведет к инстанцированию потока операционной системы, который начинает выполнять оператор operator()
с вашим функтором (или начинает выполнять функцию, переданную с помощью указателя). Пример 12.1 показывает, как это делается.
#include
#include
#include
struct MyThreadFunc {
void operator()() {
// Что-нибудь работающее долго...
}
} threadFun;
int main() {
boost::thread myThread(threadFun); // Создать поток, запускающий
// функцию threadFun
boost.:thread::yield(); // Уступить порожденному потоку квант времени.
// чтобы он мог выполнить какую-то работу.
// Выполнить какую-нибудь другую работу
myThread join(); // Текущий поток (т.е поток функции main) прежде.
// чем завершиться, будет ждать окончания myThread
}
Создается поток обманчиво просто. Вам необходимо лишь создать объект thread
в стеке или в динамической памяти и передать ему функтор, который укажет, с чего начать работу. В данном случае термин «поток» (thread) используется в двух смыслах. Во-первых, это объект класса thread
, который является обычным объектом C++. При ссылке на этот объект я буду говорить «объект потока». Кроме того, существует поток выполнения, который является потоком операционной системы, представленным объектом thread
. Когда я говорю «поток» (в отличие от названия класса потока, напечатанного моноширинным шрифтом), я имею в виду поток операционной системы.
Теперь перейдем непосредственно к рассмотрению программного кода в примере. Конструктор thread
принимает функтор (или указатель функции), имеющий два аргумента и возвращающий void
. Рассмотрим следующую строку из примера 12.1.
boost::thread myThread(threadFun);