Files
CWithClasses/Thread/Thread.md
2025-12-31 12:49:32 +08:00

4.8 KiB
Raw Permalink Blame History

哈哈哈哈,太正常了,这玩意儿本来就反直觉 😄 行,我给你一份能当速查表用的 <thread> 全家桶说明,不讲虚的,只讲:

  • 干嘛用
  • 怎么调
  • 有没有返回值
  • 什么时候该用 / 不该用

你看完这一份,再回头看你之前的代码,会突然“哦原来如此”。


一、<thread> 到底提供了什么?

严格来说 <thread> 只解决三件事

  1. 创建线程
  2. 控制线程生命周期
  3. 获取线程身份 / 状态

👉 不负责:

  • 返回值
  • 同步
  • 通信

那些是 <future><mutex><atomic> 的活。


二、std::thread(核心中的核心)

1 构造线程(创建并立刻运行)

#include <thread>

void foo(int x) {}

std::thread t(foo, 10);

本质

  • 创建 OS 线程
  • 立刻执行 foo(10)

参数规则

  • 按值拷贝
  • 要引用必须用 std::ref
int x = 10;
thread t(foo, ref(x));

返回值

没有 (线程函数的返回值会被丢弃)


2 join() —— 等线程干完

t.join();

作用

  • 阻塞当前线程
  • 直到 t 执行完

返回值

必须记住的铁律

一个 std::thread 要么 join(),要么 detach(),否则程序直接 std::terminate()


3 detach() —— 放生线程(慎用)

t.detach();

作用

  • 线程变成后台线程
  • 主线程不再管它

返回值

什么时候能用?

  • 日志
  • 心跳
  • 不依赖任何外部对象

新手忠告

90% 的 detach() 都是 bug


4 joinable() —— 能不能 join

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

什么时候 false

  • 已 join
  • 已 detach
  • 默认构造的 thread

5 get_id() —— 线程 ID

std::thread::id id = t.get_id();

用途

  • 调试
  • 日志
  • 判断是不是同一个线程

6 std::this_thread::get_id()

auto id = std::this_thread::get_id();

👉 获取当前线程的 ID


三、线程“辅助函数”(非常常用)

7 sleep_for() —— 休眠一段时间

#include <chrono>
using namespace std::chrono_literals;

std::this_thread::sleep_for(100ms);

作用

  • 让当前线程休眠

返回值


8 sleep_until() —— 睡到某个时间点

auto t = chrono::steady_clock::now() + 1s;
std::this_thread::sleep_until(t);

9 yield() —— 让出 CPU

std::this_thread::yield();

作用

  • 告诉调度器: “我不急,你先跑别人”

用途

  • 自旋锁
  • 低优先级任务

四、hardware_concurrency() —— CPU 有多少核?

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

返回值

  • 建议线程数
  • 可能是 0不保证

👉 常见用法:

int n = max(1u, thread::hardware_concurrency());

五、所有 <thread> API 一览表(重点)

API 作用 返回值
thread(f, args...) 创建并运行线程
join() 等线程结束 void
detach() 放生线程 void
joinable() 能否 join bool
get_id() 线程 ID thread::id
this_thread::get_id() 当前线程 ID thread::id
this_thread::sleep_for() 休眠 void
this_thread::sleep_until() 睡到时间点 void
this_thread::yield() 让出 CPU void
hardware_concurrency() CPU 线程数 unsigned

📌 没有一个 API 有“业务返回值”


六、那“返回值”到底去哪了?

👉 根本不在 <thread>

你要记住这个分工:

需求 用什么
跑线程 std::thread
拿返回值 std::future
简单并发任务 std::async
同步 mutex / atomic

七、你现在可以这样理解(非常重要)

std::thread ≈ C 语言 pthread_create std::async ≈ “有返回值的线程函数”

所以你刚才的崩溃是合理的 😂 你是拿 pthread 的心态,期待 Java 的体验


八、给你一条“永远不翻车”的使用准则

如果你想要返回值: 不要用 std::thread std::async


如果你愿意,下一步我可以帮你做三件事之一:

1 把你刚才那个项目 改成 async 版本 2 给你一份 <future> 函数大全(和这份一样清楚) 3 手把手写一个 线程池(真正工程级)

你挑。