Многопоточность в С раньше не поддерживалась встроенными возможностями, а достигалась только путем применения дополнительных инструментов или специальных методов программирования. В последних версиях языка многопоточность поддерживается встроенным инструментом. Многопоточность тесно связана с другим термином — многозадачностью. Начинающие разработчики путают два эти термина, а это неправильно.
Многозадачность свойственна устройствам, средам выполнения и операционным системам и несет в себе возможность параллельно и одновременно обрабатывать несколько поставленных задач. Задачи не связаны между собой и могут обрабатываться отдельно друг от друга.
Многопоточность свойственна программам и несет в себе возможность обрабатывать эту программу в несколько параллельных и одновременных потоков. Потоки одной программы тесно связаны между собой и не могут исполняться отдельно друг от друга.
Поток является отдельной ветвью кода одной программы, которая может выполняться параллельно с другими ветвями кода этой же программы.
Например, вы включаете на компьютере аудиоплеер с вашей любимой музыкой, запускаете редактор кода, чтобы программировать, и при этом ищете через поиск в браузере нужную информацию в интернете, потому что вы столкнулись с проблемой в программировании и не знаете, как ее решить. Аудиоплеер, редактор кода и браузер — это часть многозадачности вашей операционной системы. Работая в браузере, вы открываете несколько вкладок — вкладки будут частью многопоточности браузера.
Многопоточность в С
Раньше многопоточность в С реализовывалась с применением дополнительных кроссплатформенных библиотек, например:
OpenMP;
OpenTheads;
POCO Thead;
Zthread;
Pthreads-w32;
и др.
В «свежих» языках Си многопоточность реализовывается при помощи класса «std::thread», где «std::thread» является классом каждого отдельного потока. Теперь новый поток запускается довольно просто: необходимо создавать новый объект потока и передавать исполняемый код для вызова в конструктор объекта. При создании нового объекта будет запускаться новый поток.
Многопоточность в Си: класс «std::thread»
Чтобы использовать многопоточность в С, необходимо выполнить ряд действий:
Обязательно записать заголовочный файл «#include <thread>».
Каждый отдельный поток обозначать классом «std::thread t(callable_object, arg1, arg2 ..)».
Как выглядит запуск потока в С на примере:
#include <iostream>
#include <thread>
#include <string>
void say_hello(const std::string& name) {
std::cout << "Привет! " << name << std::endl;
}
int main(int argc, char * argv[]) {
std::thread th(say_hello, "Мир!");
th.join();
return 0;
}
Особенности класса «std::thread»:
его нельзя копировать, но можно перемещать и присваивать другим объектам, которые не имеют связи с другими потоками;
у каждого потока должен быть свой идентификатор, который возможно узнать, применив метод «get_id»;
можно использовать статический метод «hardware_concurrency», возвращающий количество параллельных потоков;
можно использовать статические методы для «усыпления» потоков: «sleep_for» или «sleep_until»;
при необходимости можно передать управление другим потокам при помощи функции «yield»;
класс может вызывать объекты трех видов: указатель на функцию, функциональный объект, лямбда-выражение.
Запускаем новый поток с применением указателя на функцию следующим образом:
void foo(parameters)
{
//описываем действие, которое необходимо сделать
}
std::thread thread_object(foo, parameters)
Запускаем новый поток с применением функционального объекта следующим образом:
// Для начала необходимо определить класс объекта функции
class fn_obj_class {
void operator() (parameters)
{
//Описываем действие, которое необходимо выполнить
}
}
//создаем объект потока
std::thread thread_object(fn_class_obj(), parameters)
Запускаем новый поток с применением лямбда-выражения следующим образом:
//Для начала необходимо определить лямбда-выражение
auto x = [] (parameters) {
//Описываем действия, которые необходимо выполнить
};
//необходимо передать «х» и его параметры в конструктор объекта
std:: thread thread_object (x, parameters);
Заключение
Многопоточность в С и в других языках программирования играет важную роль, потому что позволяет улучшить производительность написанных программ за счет правильного использования возможностей мультизадачности и мультипроцессирования операционных систем. Поэтому при написании сложных программ важно изучить тонкости многопоточности и уметь их применять на практике.
Другое