Skip to main content
Version: Next

thread

std::thread 是 C++11 引入的线程类,用于创建和管理原生线程。它让 C++ 程序可以并发执行多个任务,从而更好利用多核 CPU。

和早期平台相关线程 API 相比,std::thread 提供了跨平台、类型安全且更现代的接口模型。

头文件与基本特征

使用线程时,通常包含:

#include <thread>

主要特征:

特征说明
作用启动并管理一个执行线程
所有权thread 对象拥有线程句柄
是否可拷贝不可拷贝
是否可移动可移动
生命周期要求可 join 的线程在析构前必须 join()detach()

基本用法

创建线程最常见的方式:

#include <iostream>
#include <thread>

void work() {
std::cout << "worker running\n";
}

int main() {
std::thread t(work);
t.join();
return 0;
}

join() 会等待线程执行结束,是最常见的收尾方式。

也可以直接传 lambda:

std::thread t([] {
// do something
});
t.join();

交互演示(MDX + React)

下面这个演示面板用于可视化 thread 的状态流转:启动、运行、完成、joindetachmove

std::thread 生命周期演示

模拟线程对象从启动到 join/detach 的典型状态流转。

MDX + React
worker stateempty
joinable()false
next worker id1
任务耗时500 ms
状态说明thread 对象为空,可用于启动新线程。

线程控制

演示参数

最近操作

  • 初始化: thread 对象为空,不可 join

join 与 detach

join()

join() 会阻塞当前线程,直到目标线程执行结束:

std::thread t([] {
// long task
});

t.join();

调用后,线程句柄被回收,t.joinable() 变为 false

detach()

detach() 会把线程与 thread 对象分离,线程在后台继续运行:

std::thread t([] {
// background task
});

t.detach();

分离后不能再 join(),并且要确保后台线程访问的资源在其运行期间仍有效。

joinable()

joinable() 用于判断线程对象当前是否还关联着可 join 的线程:

std::thread t([] {});

if (t.joinable()) {
t.join();
}

在写通用线程清理逻辑时,joinable() 非常重要。

move 语义

std::thread 不可拷贝,但可移动:

#include <thread>

int main() {
std::thread t1([] {});
std::thread t2 = std::move(t1);

if (t2.joinable()) {
t2.join();
}
return 0;
}

移动后,原对象 t1 不再拥有线程句柄。

线程 ID 与并发信息

获取线程 ID:

#include <iostream>
#include <thread>

int main() {
std::thread t([] {
std::cout << std::this_thread::get_id() << '\n';
});

std::cout << t.get_id() << '\n';
t.join();
}

获取硬件并发提示值:

unsigned int n = std::thread::hardware_concurrency();

它只是建议值,不保证精确。

参数传递

线程函数参数默认按值复制。如果要传引用,需要 std::ref

#include <functional>
#include <thread>

void increment(int& x) {
++x;
}

int main() {
int value = 0;
std::thread t(increment, std::ref(value));
t.join();
}

休眠与让出执行权

常用工具在 <thread><chrono>

#include <chrono>
#include <thread>

std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::this_thread::yield();

sleep_for 让当前线程休眠一段时间,yield 提示调度器可切换到其他线程。

常见陷阱

  1. 忘记 join()detach():如果 thread 析构时仍是 joinable,程序会调用 std::terminate
  2. detach() 后访问悬空数据:后台线程引用了已经销毁的对象。
  3. 数据竞争:多个线程同时读写共享变量却没有同步措施(需配合 mutex、原子变量等)。
  4. 过度创建线程:线程本身有开销,不应把极小任务拆成大量线程。

与 mutex / future 的关系

  1. thread 负责“并发执行”。
  2. mutex 负责“并发访问同步”。
  3. future / promise 负责“跨线程结果传递”。

三者组合是 C++11 多线程编程的基础模型。

小结

std::thread 是 C++11 并发的入口类型。掌握线程创建、join/detachjoinable、参数传递和移动语义后,就能建立稳定的线程生命周期管理习惯,再进一步配合 mutexfuture 完成更完整的并发设计。