Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI28 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Запуск потока в C++: std::thread
В C++11 появился стандартный способ создания и управления потоками через std::thread из <thread>. Это кроссплатформенное решение работает на Windows, Linux и macOS.
Базовый способ: функция
#include <thread>
#include <iostream>
// Обычная функция
void worker() {
std::cout << "Thread is running" << std::endl;
}
int main() {
// Создаём и запускаем поток
std::thread t(worker);
// Ждём завершения потока
t.join();
std::cout << "Thread finished" << std::endl;
return 0;
}
Вывод:
Thread is running
Thread finished
Передача параметров
#include <thread>
#include <iostream>
void worker(int id, const std::string& name) {
std::cout << "Thread " << id << ": " << name << std::endl;
}
int main() {
// Передаём параметры после функции
std::thread t1(worker, 1, "Alice");
std::thread t2(worker, 2, "Bob");
t1.join(); // Ждём первого
t2.join(); // Ждём второго
return 0;
}
Вывод:
Thread 1: Alice
Thread 2: Bob
Лямбда-функция
#include <thread>
#include <iostream>
int main() {
int value = 42;
// Лямбда с захватом переменных
std::thread t([value]() {
std::cout << "Value: " << value << std::endl;
});
t.join();
return 0;
}
Методы класса
#include <thread>
#include <iostream>
class Worker {
public:
void do_work(int id) {
std::cout << "Worker " << id << " is working" << std::endl;
}
};
int main() {
Worker w;
// Передаём объект, метод и параметры
std::thread t(&Worker::do_work, &w, 1);
t.join();
return 0;
}
Функтор (объект функции)
#include <thread>
#include <iostream>
class ThreadTask {
public:
void operator()(int value) {
std::cout << "Task with value: " << value << std::endl;
}
};
int main() {
// Осторожно с копированием!
std::thread t(ThreadTask(), 100);
t.join();
return 0;
}
Множество потоков
#include <thread>
#include <vector>
#include <iostream>
void worker(int id) {
std::cout << "Thread " << id << std::endl;
}
int main() {
std::vector<std::thread> threads;
// Создаём 5 потоков
for (int i = 0; i < 5; i++) {
threads.emplace_back(worker, i);
}
// Ждём всех
for (auto& t : threads) {
t.join();
}
return 0;
}
RAII для потоков
#include <thread>
#include <iostream>
class ThreadGuard {
private:
std::thread t;
public:
template<typename Function>
ThreadGuard(Function f) : t(f) {}
~ThreadGuard() {
if (t.joinable()) {
t.join(); // Автоматический join при выходе
}
}
};
int main() {
{
ThreadGuard g([]() { std::cout << "Working" << std::endl; });
} // Поток ждёт завершения в деструкторе
return 0;
}
Переход в фоновый режим (detach)
#include <thread>
#include <iostream>
#include <chrono>
void background_task() {
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "Background task done" << std::endl;
}
int main() {
std::thread t(background_task);
// Отделяем поток - он работает независимо
t.detach();
// Основной поток продолжает
std::cout << "Main thread continues" << std::endl;
// Важно: дождитесь завершения перед выходом!
std::this_thread::sleep_for(std::chrono::seconds(2));
return 0;
}
Вывод:
Main thread continues
Background task done
Захват переменных в лямбде
#include <thread>
#include <iostream>
int main() {
int x = 10;
int y = 20;
// [=] — захват всех по значению
std::thread t1([=]() {
std::cout << "x=" << x << ", y=" << y << std::endl;
});
t1.join();
// [&] — захват всех по ссылке (опасно!)
std::thread t2([&]() {
std::cout << "x=" << x << ", y=" << y << std::endl;
});
t2.join();
// [=, &y] — захват x по значению, y по ссылке
std::thread t3([=, &y]() {
std::cout << "x=" << x << ", y=" << y << std::endl;
});
t3.join();
return 0;
}
Синхронизация потоков: mutex
#include <thread>
#include <mutex>
#include <iostream>
int counter = 0;
std::mutex m;
void increment() {
for (int i = 0; i < 1000; i++) {
std::lock_guard<std::mutex> lock(m); // RAII блокировка
counter++; // Безопасно
}
}
int main() {
std::thread t1(increment);
std::thread t2(increment);
t1.join();
t2.join();
std::cout << "Counter: " << counter << std::endl; // 2000
return 0;
}
Передача данных между потоками: условная переменная
#include <thread>
#include <mutex>
#include <condition_variable>
#include <iostream>
#include <queue>
std::queue<int> data_queue;
std::mutex m;
std::condition_variable cv;
bool ready = false;
void producer() {
std::lock_guard<std::mutex> lock(m);
data_queue.push(42);
ready = true;
cv.notify_one(); // Пробудить потребителя
}
void consumer() {
std::unique_lock<std::mutex> lock(m);
cv.wait(lock, []() { return ready; }); // Ждём сигнала
int value = data_queue.front();
data_queue.pop();
std::cout << "Received: " << value << std::endl;
}
int main() {
std::thread p(producer);
std::thread c(consumer);
p.join();
c.join();
return 0;
}
ID потока и процессорные ядра
#include <thread>
#include <iostream>
int main() {
// Получить ID текущего потока
std::cout << "Main thread ID: " << std::this_thread::get_id() << std::endl;
std::thread t([]() {
std::cout << "Worker thread ID: " << std::this_thread::get_id() << std::endl;
});
// Количество логических ядер
unsigned int cores = std::thread::hardware_concurrency();
std::cout << "Available cores: " << cores << std::endl;
t.join();
return 0;
}
Обработка исключений в потоках
#include <thread>
#include <iostream>
void risky_task() {
throw std::runtime_error("Something went wrong!");
}
int main() {
std::thread t(risky_task);
try {
t.join(); // Исключение выбросится здесь!
} catch (const std::exception& e) {
std::cout << "Exception caught: " << e.what() << std::endl;
}
return 0;
}
Ошибка: забыли join() или detach()
#include <thread>
#include <iostream>
int main() {
{
std::thread t([]() { std::cout << "Hello" << std::endl; });
// БЕЗ t.join() — программа завершится аварийно!
// t.join(); // Нужно добавить
} // Ошибка: terminate called!
return 0;
}
Правильный паттерн
#include <thread>
#include <vector>
int main() {
std::vector<std::thread> threads;
// Создание
for (int i = 0; i < 4; i++) {
threads.emplace_back([i]() {
// Работа
});
}
// Ожидание
for (auto& t : threads) {
if (t.joinable()) {
t.join();
}
}
return 0;
}
Вывод
- std::thread(function, args) — создание и запуск
- join() — ждём завершения потока
- detach() — отделяем поток (осторожно!)
- mutex + lock_guard — синхронизация доступа
- condition_variable — сигналы между потоками
- Всегда join() или detach() перед выходом
- Используй RAII для гарантированного join()
- hardware_concurrency() — количество ядер для оптимизации