CppStack

C++技术栈一站式学习 · ‌业精于勤,荒于嬉;行成于思,毁于随。

C++ 标准中的并发与多线程支持

Tags = [ C++Std ]

std::threadstd::barrier

C++ 从 C++11 开始正式引入标准化的并发支持,包括 std::thread、std::mutex、std::future 等基础设施;C++17 增加了 std::shared_mutex 以优化读多写少场景;C++20 带来了协程、std::jthread 与 std::stop_token,简化线程管理与取消;C++23 则补充了 std::barrier、std::latch 等同步原语,逐步构建起完整的并发编程模型。


1. C++11:并发的起点

C++11 是并发支持的里程碑,首次将多线程纳入标准库。主要特性包括:

  • std::thread:创建和管理线程
  • std::mutex / std::lock_guard:互斥锁
  • std::future / std::async:任务并行与结果获取

示例:std::threadstd::mutex

#include <iostream>
#include <thread>
#include <mutex>

std::mutex mtx;
int counter = 0;

void worker(int id) {
    for (int i = 0; i < 5; ++i) {
        std::lock_guard<std::mutex> lock(mtx);
        ++counter;
        std::cout << "Thread " << id << " incremented counter to " << counter << "\n";
    }
}

int main() {
    std::thread t1(worker, 1);
    std::thread t2(worker, 2);

    t1.join();
    t2.join();

    std::cout << "Final counter = " << counter << "\n";
    return 0;
}

示例:std::futurestd::async

#include <iostream>
#include <future>

int compute_square(int x) {
    return x * x;
}

int main() {
    std::future<int> fut = std::async(std::launch::async, compute_square, 12);

    std::cout << "Computing square...\n";
    int result = fut.get();  // 阻塞等待结果
    std::cout << "Result = " << result << "\n";
    return 0;
}

2. C++17:读写锁 std::shared_mutex

C++17 引入了 共享互斥锁

  • std::shared_mutex:允许多个线程同时读,但写操作需要独占。
  • std::shared_lock:读锁。
  • std::unique_lock:写锁。

示例:读写锁

#include <iostream>
#include <thread>
#include <shared_mutex>
#include <vector>

std::shared_mutex rw_mutex;
std::vector<int> data;

void reader(int id) {
    std::shared_lock lock(rw_mutex);
    std::cout << "Reader " << id << " sees size = " << data.size() << "\n";
}

void writer(int value) {
    std::unique_lock lock(rw_mutex);
    data.push_back(value);
    std::cout << "Writer added " << value << "\n";
}

int main() {
    std::thread w1(writer, 42);
    std::thread r1(reader, 1);
    std::thread r2(reader, 2);

    w1.join();
    r1.join();
    r2.join();
    return 0;
}

3. C++20:协程与可控线程

C++20 在并发方面有三大亮点:

  • 协程(coroutines):语言级支持异步编程。
  • std::jthread:自动 join 的线程,避免忘记 join()detach()
  • std::stop_token:线程可控终止机制。

示例:std::jthreadstd::stop_token

#include <iostream>
#include <thread>
#include <chrono>

void worker(std::stop_token st) {
    int i = 0;
    while (!st.stop_requested()) {
        std::cout << "Working... " << i++ << "\n";
        std::this_thread::sleep_for(std::chrono::milliseconds(200));
    }
    std::cout << "Worker stopped.\n";
}

int main() {
    std::jthread t(worker);  // 自动 join
    std::this_thread::sleep_for(std::chrono::seconds(1));
    t.request_stop();        // 请求停止
    return 0;
}

示例:协程(最小可运行例子)

#include <iostream>
#include <coroutine>

struct Task {
    struct promise_type {
        Task get_return_object() { return {}; }
        std::suspend_never initial_suspend() { return {}; }
        std::suspend_never final_suspend() noexcept { return {}; }
        void return_void() {}
        void unhandled_exception() { std::terminate(); }
    };
};

Task hello_coroutine() {
    std::cout << "Hello from coroutine!\n";
    co_return;
}

int main() {
    hello_coroutine();
    return 0;
}

4. C++23:同步原语 std::barrierstd::latch

C++23 引入了新的同步工具:

  • std::latch:一次性计数器,等待所有任务完成。
  • std::barrier:可重用的同步点,适合分阶段并行计算。

示例:std::latch

#include <iostream>
#include <thread>
#include <latch>
#include <vector>

void worker(std::latch& done, int id) {
    std::cout << "Worker " << id << " done.\n";
    done.count_down();
}

int main() {
    std::latch done(3);
    std::vector<std::thread> threads;

    for (int i = 0; i < 3; ++i) {
        threads.emplace_back(worker, std::ref(done), i);
    }

    done.wait();  // 等待所有线程完成
    std::cout << "All workers finished.\n";

    for (auto& t : threads) t.join();
    return 0;
}

示例:std::barrier

#include <iostream>
#include <thread>
#include <barrier>
#include <vector>

void phase_task(std::barrier<>& sync_point, int id) {
    std::cout << "Thread " << id << " reached phase 1\n";
    sync_point.arrive_and_wait();

    std::cout << "Thread " << id << " reached phase 2\n";
    sync_point.arrive_and_wait();
}

int main() {
    std::barrier sync_point(3);
    std::vector<std::thread> threads;

    for (int i = 0; i < 3; ++i) {
        threads.emplace_back(phase_task, std::ref(sync_point), i);
    }

    for (auto& t : threads) t.join();
    return 0;
}

5. 总结

C++ 并发支持的演进过程:

  1. C++11:奠基,提供 std::threadstd::mutexstd::future
  2. C++17:增强,支持 std::shared_mutex,优化读多写少场景。
  3. C++20:现代化,引入协程、std::jthreadstd::stop_token
  4. C++23:完善,提供 std::barrierstd::latch 等同步原语。

现代 C++ 已经具备了从底层线程管理到高层异步编程的完整工具链,开发者可以根据需求选择合适的抽象层次。