从 std::thread
到 std::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::thread
与 std::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::future
与 std::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::jthread
与 std::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::barrier
与 std::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++ 并发支持的演进过程:
- 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
等同步原语。
现代 C++ 已经具备了从底层线程管理到高层异步编程的完整工具链,开发者可以根据需求选择合适的抽象层次。