← Назад к вопросам
Каким вызовом создастся новый поток?
1.8 Middle🔥 161 комментариев
#Многопоточность и синхронизация#Язык C++
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Создание новых потоков в C++
Это фундаментальный вопрос многопоточного программирования. В C++ существует несколько способов создания потоков, в зависимости от версии стандарта и платформы.
1. Стандартная библиотека C++11: std::thread
Это самый современный и рекомендуемый способ. std::thread — часть стандартной библиотеки с C++11.
Создание потока с функцией
#include <thread>
#include <iostream>
void workerFunction(int id) {
std::cout << "Thread " << id << " is running\n";
}
int main() {
std::thread t1(workerFunction, 1);
t1.join();
std::cout << "Thread completed\n";
return 0;
}
Создание с лямбда-функцией
#include <thread>
#include <iostream>
int main() {
int id = 42;
std::thread t([id]() {
std::cout << "Lambda thread with id = " << id << std::endl;
});
t.join();
return 0;
}
Создание с методом класса
#include <thread>
#include <iostream>
class Worker {
public:
void doWork(int id) {
std::cout << "Worker thread " << id << " running\n";
}
};
int main() {
Worker worker;
std::thread t(&Worker::doWork, &worker, 1);
t.join();
return 0;
}
2. POSIX потоки (pthread)
Это низкоуровневый API, используется в системном программировании. Работает на Unix/Linux.
#include <pthread.h>
#include <iostream>
void* threadFunction(void* arg) {
int* id = (int*)arg;
std::cout << "POSIX thread " << *id << " running\n";
delete id;
return nullptr;
}
int main() {
pthread_t thread1;
int* threadId = new int(1);
int result = pthread_create(&thread1, nullptr, threadFunction, threadId);
if (result != 0) {
std::cerr << "Error creating thread\n";
return 1;
}
pthread_join(thread1, nullptr);
return 0;
}
3. Windows API: CreateThread
Для Windows систем, даёт больше контроля.
#include <windows.h>
#include <iostream>
DWORD WINAPI ThreadFunction(LPVOID param) {
int* id = (int*)param;
std::cout << "Windows thread " << *id << " running\n";
delete id;
return 0;
}
int main() {
HANDLE hThread;
int* threadId = new int(1);
hThread = CreateThread(
nullptr,
0,
ThreadFunction,
threadId,
0,
nullptr
);
if (hThread == nullptr) {
std::cerr << "Error creating thread\n";
return 1;
}
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
return 0;
}
4. Управление потоками
join() vs detach()
#include <thread>
#include <chrono>
#include <iostream>
int main() {
std::thread t1([]() {
std::this_thread::sleep_for(std::chrono::seconds(2));
std::cout << "Thread 1 finished\n";
});
std::thread t2([]() {
std::cout << "Thread 2 starting\n";
});
t1.join(); // Блокирует, ждет завершения
t2.join(); // Ждем t2
return 0;
}
join() — блокирует вызывающий поток до завершения целевого потока detach() — отделяет поток, он работает независимо
Синхронизация потоков
#include <thread>
#include <mutex>
#include <iostream>
std::mutex m;
int sharedData = 0;
void incrementData() {
std::lock_guard<std::mutex> lock(m);
sharedData++;
std::cout << "Data: " << sharedData << std::endl;
}
int main() {
std::thread t1(incrementData);
std::thread t2(incrementData);
std::thread t3(incrementData);
t1.join();
t2.join();
t3.join();
return 0;
}
5. Частые ошибки
Забыли join/detach
// НЕПРАВИЛЬНО!
int main() {
std::thread t([]() {
std::cout << "Thread running\n";
});
return 0; // Программа завершится, поток будет убит
}
// ПРАВИЛЬНО:
int main() {
std::thread t([]() {
std::cout << "Thread running\n";
});
t.join(); // Ждём завершения
return 0;
}
Захват по ссылке в лямбда
// НЕПРАВИЛЬНО!
int main() {
int x = 42;
std::thread t([&x]() { // Захват по ссылке опасен
std::cout << x << std::endl;
});
return 0; // x может быть удалена до выполнения потока
}
// ПРАВИЛЬНО:
int main() {
int x = 42;
std::thread t([x]() { // Захват по значению
std::cout << x << std::endl;
});
t.join();
return 0;
}
6. RAII pattern для потоков
class ThreadGuard {
std::thread t;
public:
ThreadGuard(std::thread&& thread) : t(std::move(thread)) {}
~ThreadGuard() {
if (t.joinable()) t.join();
}
ThreadGuard(const ThreadGuard&) = delete;
ThreadGuard& operator=(const ThreadGuard&) = delete;
};
int main() {
ThreadGuard tg(std::thread([]() {
std::cout << "Safe thread execution\n";
}));
return 0; // Автоматически join'ится
}
Сравнение способов
| Способ | Язык | Платформа | Уровень | Когда использовать |
|---|---|---|---|---|
| std::thread | C++11+ | Кросс-платформа | Высокий | Всегда (рекомендуется) |
| pthread | C | Unix/Linux | Средний | Системное ПО, legacy код |
| CreateThread | C++ | Windows | Средний | Windows-специфика |
Best Practices
- Всегда используй std::thread для новых проектов
- Всегда вызывай join() или detach() — иначе программа упадёт
- Используй RAII для автоматического управления потоками
- Синхронизируй общие данные с помощью mutex
- Избегай захвата по ссылке в лямбда для потоков
- Передавай параметры напрямую конструктору std::thread, не захватывай переменные
Вывод: Для современного C++ (C++11 и выше) используй std::thread. Это кросс-платформенный, безопасный и удобный способ создания потоков. Помни о RAII и синхронизации!