std::thread 深度解析
C++11 引入的
std::thread让多线程编程成为标准库的一部分,告别平台相关的 pthread/Win32 API。
基本用法
cpp
#include <thread>
#include <iostream>
void worker(int id, const std::string& msg) {
std::cout << "线程 " << id << ": " << msg << "\n";
}
int main() {
// 创建线程
std::thread t1(worker, 1, "hello");
std::thread t2(worker, 2, "world");
// 必须 join 或 detach,否则析构时 terminate()
t1.join(); // 等待线程结束
t2.detach(); // 分离线程(后台运行,不再管理)
// Lambda 线程
std::thread t3([](int x) {
std::cout << "lambda: " << x << "\n";
}, 42);
t3.join();
// 获取线程 ID
std::cout << "主线程 ID: " << std::this_thread::get_id() << "\n";
std::cout << "硬件并发数: " << std::thread::hardware_concurrency() << "\n";
}RAII 线程包装
cpp
// std::thread 析构时如果未 join/detach 会 terminate()
// 用 RAII 包装确保安全
class JoinThread {
std::thread t_;
public:
template<typename F, typename... Args>
explicit JoinThread(F&& f, Args&&... args)
: t_(std::forward<F>(f), std::forward<Args>(args)...) {}
~JoinThread() {
if (t_.joinable()) t_.join();
}
JoinThread(JoinThread&&) = default;
JoinThread& operator=(JoinThread&&) = default;
JoinThread(const JoinThread&) = delete;
JoinThread& operator=(const JoinThread&) = delete;
};
// C++20 std::jthread:自动 join 的线程
#include <thread>
{
std::jthread t([](std::stop_token st) {
while (!st.stop_requested()) {
// 工作...
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
});
// 析构时自动请求停止并 join
}线程间数据共享
cpp
#include <mutex>
#include <thread>
#include <vector>
// 问题:数据竞争
int counter = 0;
void bad_increment() {
for (int i = 0; i < 100000; ++i) ++counter; // 数据竞争!
}
// 解决:互斥锁
std::mutex mtx;
int safe_counter = 0;
void safe_increment() {
for (int i = 0; i < 100000; ++i) {
std::lock_guard<std::mutex> lock(mtx);
++safe_counter;
}
}
// 更高效:原子操作
#include <atomic>
std::atomic<int> atomic_counter{0};
void atomic_increment() {
for (int i = 0; i < 100000; ++i) ++atomic_counter;
}
int main() {
std::vector<std::thread> threads;
for (int i = 0; i < 4; ++i)
threads.emplace_back(atomic_increment);
for (auto& t : threads) t.join();
std::cout << atomic_counter << "\n"; // 400000
}线程局部存储
cpp
// thread_local:每个线程有独立副本
thread_local int tls_counter = 0;
thread_local std::string tls_name;
void worker(const std::string& name) {
tls_name = name;
for (int i = 0; i < 5; ++i) ++tls_counter;
std::cout << tls_name << ": " << tls_counter << "\n";
}
// 每个线程的 tls_counter 独立,不需要同步
std::thread t1(worker, "Alice");
std::thread t2(worker, "Bob");
t1.join(); t2.join();线程池实现
cpp
#include <thread>
#include <queue>
#include <mutex>
#include <condition_variable>
#include <functional>
#include <future>
class ThreadPool {
std::vector<std::thread> workers_;
std::queue<std::function<void()>> tasks_;
std::mutex mtx_;
std::condition_variable cv_;
bool stop_ = false;
public:
explicit ThreadPool(size_t n) {
for (size_t i = 0; i < n; ++i) {
workers_.emplace_back([this] {
while (true) {
std::function<void()> task;
{
std::unique_lock lock(mtx_);
cv_.wait(lock, [this] {
return stop_ || !tasks_.empty();
});
if (stop_ && tasks_.empty()) return;
task = std::move(tasks_.front());
tasks_.pop();
}
task();
}
});
}
}
template<typename F, typename... Args>
auto submit(F&& f, Args&&... args) {
using R = std::invoke_result_t<F, Args...>;
auto task = std::make_shared<std::packaged_task<R()>>(
std::bind(std::forward<F>(f), std::forward<Args>(args)...)
);
std::future<R> fut = task->get_future();
{
std::lock_guard lock(mtx_);
if (stop_) throw std::runtime_error("线程池已停止");
tasks_.emplace([task]{ (*task)(); });
}
cv_.notify_one();
return fut;
}
~ThreadPool() {
{ std::lock_guard lock(mtx_); stop_ = true; }
cv_.notify_all();
for (auto& t : workers_) t.join();
}
};
// 使用
ThreadPool pool(4);
auto f1 = pool.submit([](int x) { return x * x; }, 5);
auto f2 = pool.submit([]{ return std::string("hello"); });
std::cout << f1.get() << "\n"; // 25
std::cout << f2.get() << "\n"; // hellostd::jthread 与协作式取消(C++20)
cpp
#include <thread>
#include <stop_token>
// jthread 支持协作式取消
std::jthread worker([](std::stop_token st) {
int count = 0;
while (!st.stop_requested()) {
std::cout << "工作中... " << count++ << "\n";
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
std::cout << "收到停止信号,退出\n";
});
std::this_thread::sleep_for(std::chrono::seconds(1));
worker.request_stop(); // 请求停止
worker.join(); // 等待结束
// stop_callback:停止时执行回调
std::stop_source ss;
std::stop_callback cb(ss.get_token(), [] {
std::cout << "停止回调执行\n";
});
ss.request_stop(); // 触发回调关键认知
std::thread 析构时必须已 join 或 detach,否则程序终止。C++20 的 std::jthread 自动 join 且支持协作式取消,是更好的选择。线程间共享数据用 std::mutex 或 std::atomic,优先用原子操作(更快)。