Многопоточность в C++ с примерами

Многопоточность в C++Что такое поток? Поток — это рабочая единица определенного процесса. В мультипрограммных операционных системах одновременно выполняются разные процессы.

Аналогичным образом мы можем захотеть одновременно выполнять одни и те же экземпляры процессов. В этом случае каждый экземпляр процесса назначается исполнительной единице, называемой потоком. В многопоточной системе множество потоков выполняются одновременно независимо друг от друга.

До сегодняшней C++ была поддержка потоков POSIX. Но у этой функции были серьезные проблемы с переносимостью, поскольку она работала только в операционных системах Linux или UNIX. Таким образом, начиная с C++ 11-ой версии, появился единственный класс std::thread, который определяет всю функциональность для потоков. Классы и функции определены в заголовочном файле.

Работа с <thread>

Используя std::thread, нам просто нужно создать новый объект потока и передать ему вызываемый объект. Вызываемый объект — это исполняемый код, который мы хотим выполнить во время работы потока. Поэтому всякий раз, когда нам нужен новый поток, мы просто создаем объект std::thread и передаем вызываемый объект в качестве аргумента его конструктору.

Читать также:  Использование массивов с функциями в C++

После создания объекта std::thread запускается новый поток и выполняется код, предоставленный вызываемым объектом.

Давайте посмотрим, как мы можем определить вызываемый объект, который будет предоставлен объекту потока.

Вызываемый объект может быть определен тремя способами:

1) Использование функционального объекта

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

std::thread thread_object(functioObject_class (), params)

Обратите внимание на способ определения объекта потока. В качестве первого параметра конструктору объекта потока мы предоставляем перегруженную функцию, а затем указываем ее аргументы (params) в качестве второго аргумента.

2) Использование указателя функции

Вызываемый объект с помощью указателя функции может быть определен следующим образом:

Как только мы определим эту функцию, мы можем создать объект потока с этой функцией как вызываемой следующим образом:

std::thread thread_obj(funct_call, params);

Обратите внимание, что аргументы (params), передаваемые функции, указываются после имени функции в объекте потока.

Читать также:  Операции ввода-вывода файла в C++

3) Использование лямбда-выражения

Мы также можем получить вызываемый объект как лямбда-выражение и передавать его объекту потока для выполнения. Фрагмент кода показан ниже:

std::thread thread_object(f, params);

В приведенном выше коде мы определили лямбда-выражение f, а затем передали его конструктору объекта потока в качестве первого аргумента, за которым следуют его параметры (params) в качестве второго аргумента.

std::thread join method

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

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

Класс std::thread предоставляет метод join(), который гарантирует, что текущий поток (pointed by *this) завершится первым, прежде чем будут предприняты какие-либо другие действия.

Вот пример:

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

Читать также:  Полиморфизм времени выполнения в C++

Пример потока

Мы представляем полный пример кода для создания и выполнения потока в программе, показанной ниже:

Вывод данных:

В приведенном выше примере мы создали три потока, используя три разных вызываемых объекта, то есть указатель функции, объект и лямбда-выражение. Мы создаем 2 экземпляра каждого потока и запускаем их. Как показано в выводных данных, три потока работают одновременно независимо друг от друга.

Итог

В этой статье мы рассмотрели концепции многопоточности в C++ на наглядном примере. В нашей следующей статье мы изучим различные аспекты шаблонов в C++.

С Уважением, МониторБанк

Добавить комментарий