c++线程补充
线程
std::make_unique<std::thread>(…)结合智能指针和线程管理
本质就做了三件事情:
- 创建一个线程(thread)
- 把这个线程对象放在堆上(heap)
- 用一个“会自动帮你收尾”的智能指针来管理它
线程对象
std::thread就是一个c++标准库的类
在 C++ 中,一个线程对象就是:
1 | std::thread t(func); |
意思是:
“启动一个新线程,让它从
func开始执行”
其中创建线程在栈和堆上有所不同:
栈
1 | void f() { |
特点:
1.自动创建
2.由于栈的生命周期,函数结束就自动销毁
但是,如果在这个std::thread对象析构时,线程还在运行(joinable),程序必须直接终止(std::terminate)
其中,std::thread 对象(C++ 层面的“控制器”)
- 它只是一个 C++ 对象
- 用来:
- 创建线程
- 管理线程句柄
- 调用
join()/detach()
而 操作系统线程(OS Thread)
- 真正执行函数代码的东西
- 由操作系统调度
- 一旦创建,就独立于 C++ 对象存在
线程函数是由“操作系统线程”执行的
而不是由 std::thread 对象执行的
所有线程对象的生命周期必须覆盖线程执行期,如果做不到就要:
要 join()
要 detach()
否则 直接终止程序
1 | t.join(); |
意思是:
“我等你跑完,然后我们一起安全退出”
- 线程函数结束
- OS 线程结束
std::thread对象变为 non-joinable- 析构安全
1 | t.detach(); |
意思是:
“我不管你了,你自生自灭”
- OS 线程继续跑
std::thread对象放弃控制权- 析构安全
但你必须保证线程访问的资源仍然活着
其中,joinable() 表示:
这个 std::thread 对象当前是否“仍然拥有一个尚未被回收的 OS 线程”。
如果返回 true,意味着:
- 线程 还没被 join
- 线程 还没被 detach
- 或者 线程已经结束,但你还没回收它
堆(heap)
1 | std::thread* t = new std::thread(work); |
特点:
- 手动管理
- 生命周期不受作用域限制
但问题更大:
- 忘记
delete→ 内存泄漏 - 异常中断 →
delete永远不会执行 - 谁负责
join()?谁负责delete?逻辑混乱
所以在堆上最好使用智能指针自动管理。
std::unique_ptr<T> 有两个核心规则:
- 独占所有权
- 同一时间只能有一个 owner
- 生命周期结束 → 自动释放资源
这一句:
1 | auto t = std::make_unique<std::thread>(work); |
等价写法是:
1 | std::thread* raw = new std::thread(work); |
也就是说:
- 在堆上
new了一个std::thread - 线程立刻启动,开始执行
work - 用
unique_ptr接管这个指针的“生杀大权”
启动线程:把一个“裸 this 指针”拷贝进新线程 auto t = std::make_unique\<std::thread>(&CameraProcessor::processingLoop, this); 这行代码会立刻启动一个新线程,在线程中执行 this->processingLoop()
线程只保存 this 的裸指针,不管理对象生命周期
如果对象先析构而线程还在跑,继续用 this → 未定义行为(可能直接崩)
// 最低安全写法:析构前一定要结束线程
1 | ~CameraProcessor() { |