C++ 中 std::thread
的高级应用、常见坑,以及如何封装为类,适合做线程池、异步任务、后台 worker、并发调度等场景。内容结构如下:
一、std::thread
高级用法清单
1. 线程成员函数调用(this 捕获)
class Worker {
public:void run() {std::thread t(&Worker::doWork, this); t.detach();}void doWork() {std::cout << "Running in thread: " << std::this_thread::get_id() << std::endl;}
};
2. 使用 Lambda 或函数对象启动线程
std::thread t([] {std::cout << "Lambda in thread\n";
});
t.join();
二、注意事项 & 常见坑
⚠️ 问题 | 原因 |
---|
std::terminate() 崩溃 | 线程创建后未 join 或 detach |
传引用未用 std::ref | 参数拷贝错误或未生效 |
多线程访问共享变量 | 没加锁或未使用原子操作 |
类内线程管理失控 | 析构时线程未清理,资源泄漏或崩溃 |
三、封装线程为类成员的完整模板
#include <iostream>
#include <thread>
#include <atomic>
#include <chrono>class ThreadWorker {
public:ThreadWorker() : m_running(false) {}~ThreadWorker() {stop(); }void start() {m_running = true;m_thread = std::thread(&ThreadWorker::threadFunc, this);}void stop() {if (m_running) {m_running = false;if (m_thread.joinable()) {m_thread.join();}}}private:void threadFunc() {while (m_running) {std::cout << "[Thread] Working... " << std::this_thread::get_id() << std::endl;std::this_thread::sleep_for(std::chrono::milliseconds(500));}std::cout << "[Thread] Exiting." << std::endl;}std::thread m_thread;std::atomic<bool> m_running;
};
使用方法:
int main() {ThreadWorker worker;worker.start();std::this_thread::sleep_for(std::chrono::seconds(2));worker.stop();
}
四、进阶封装建议(适合线程池设计)
1. 使用 std::function<void()>
注册任意任务
std::function<void()> task = [] { std::cout << "Job\n"; };
2. 使用 std::queue
+ mutex
+ condition_variable
管理任务队列
五、其他高级工具组合推荐
工具 | 用途 |
---|
std::future , std::promise | 任务结果异步获取 |
std::packaged_task | 把函数打包为可异步执行任务 |
std::atomic | 原子变量,轻量线程同步 |
condition_variable | 多线程通信唤醒机制 |
总结建议
- ✅ 线程内部用
std::atomic<bool>
控制退出比 bool 更安全 - ✅ 类内线程要在析构时妥善停止并 join
- ✅ 避免裸线程泄露:用类、封装、RAII 管理生命周期
- ✅ 封装成线程池/任务队列是多线程项目的基础