创建线程
C++ 使用 std::thread 创建线程。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| #include <iostream> #include <thread>
void task() { std::cout << "子线程执行" << std::endl; }
int main() { std::thread t(task);
t.join();
return 0; }
|
join
join() 表示等待子线程执行结束。
1 2
| std::thread t(task); t.join();
|
如果主线程不等待子线程,程序可能提前结束。
detach
detach() 表示让线程在后台独立运行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| #include <iostream> #include <thread> #include <chrono>
void task() { std::this_thread::sleep_for(std::chrono::seconds(1)); std::cout << "后台线程执行完成" << std::endl; }
int main() { std::thread t(task);
t.detach();
std::cout << "主线程结束" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(2));
return 0; }
|
注意:
detach() 后线程不再受当前 std::thread 对象管理。
使用时要特别注意:
- 不要访问已经销毁的局部变量
- 不要依赖主线程生命周期
- 不容易控制线程退出
joinable
joinable() 用于判断线程是否还可以被 join() 或 detach()。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| #include <iostream> #include <thread>
void task() { std::cout << "任务执行" << std::endl; }
int main() { std::thread t(task);
if (t.joinable()) { t.join(); }
return 0; }
|
如果一个 std::thread 对象析构时仍然是 joinable 状态,程序会调用 std::terminate()。
所以必须保证线程对象析构前已经:
向线程传递参数
值传递
1 2 3 4 5 6 7 8 9 10 11 12 13
| #include <iostream> #include <thread>
void print(int x) { std::cout << "x = " << x << std::endl; }
int main() { std::thread t(print, 10); t.join();
return 0; }
|
引用传递
如果要传引用,需要使用 std::ref。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| #include <iostream> #include <thread> #include <functional>
void add(int& x) { x += 10; }
int main() { int value = 5;
std::thread t(add, std::ref(value)); t.join();
std::cout << value << std::endl;
return 0; }
|
输出:
线程中的 lambda
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| #include <iostream> #include <thread>
int main() { int x = 10;
std::thread t([x] { std::cout << "x = " << x << std::endl; });
t.join();
return 0; }
|
如果使用引用捕获:
1 2 3
| std::thread t([&x] { x += 1; });
|
要确保变量 x 在线程结束前仍然有效。
获取线程 ID
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| #include <iostream> #include <thread>
void task() { std::cout << "子线程 ID: " << std::this_thread::get_id() << std::endl; }
int main() { std::thread t(task);
std::cout << "主线程 ID: " << std::this_thread::get_id() << std::endl;
t.join();
return 0; }
|
获取硬件并发数
1 2 3 4 5 6 7 8 9 10
| #include <iostream> #include <thread>
int main() { unsigned int n = std::thread::hardware_concurrency();
std::cout << "硬件支持的并发线程数: " << n << std::endl;
return 0; }
|
注意:
hardware_concurrency() 返回的是一个提示值,不保证一定准确。
线程休眠与让出 CPU
sleep_for
让当前线程休眠指定时间。
1 2 3 4 5 6 7 8 9 10 11 12 13
| #include <iostream> #include <thread> #include <chrono>
int main() { std::cout << "开始" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "1 秒后继续执行" << std::endl;
return 0; }
|
yield
主动让出 CPU,让调度器选择其他线程执行。
1 2 3
| #include <thread>
std::this_thread::yield();
|
RAII 线程封装
为了避免忘记 join(),可以封装一个自动 join 的线程类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| #include <thread> #include <iostream>
class JoiningThread { private: std::thread t;
public: explicit JoiningThread(std::thread thread) : t(std::move(thread)) {}
~JoiningThread() { if (t.joinable()) { t.join(); } }
JoiningThread(const JoiningThread&) = delete; JoiningThread& operator=(const JoiningThread&) = delete;
JoiningThread(JoiningThread&&) = default; JoiningThread& operator=(JoiningThread&&) = default; };
void task() { std::cout << "任务执行" << std::endl; }
int main() { JoiningThread jt(std::thread(task));
return 0; }
|
C++20 中可以使用 std::jthread,析构时会自动 join。