Skip to content

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";  // hello

std::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::mutexstd::atomic,优先用原子操作(更快)。

系统学习 C++ 生态,深入底层架构