文章目录
C++中的 sync stream
是指在多线程环境下同步输出流的概念. 在 C++20 标准中实现了 std::osyncstream
相关功能, 用于解决多线程输出流竞争和混乱问题.
1. 背景: 多线程输出的混乱
在多线程环境下, 多个线程同时向 std::cout
或其他输出流写入数据时, 常会导致输出内容交错和混乱.
举一个简单的示例:
#include <iostream>
#include <thread>
#include <vector>
int main() {
constexpr int num_thread = 10;
std::vector<std::thread> threads;
// 开启线程
for (int i = 0; i < num_thread; i++) {
threads.emplace_back(
[](int id) { std::cout << "Thread " << id << " is doing job\n"; }, i);
}
// 等待线程结束
for (auto& t : threads) {
t.join();
}
return 0;
}
我们通常会希望得到如下输出(线程顺序可能不同):
Thread 0 is doing job
Thread 2 is doing job
Thread 3 is doing job
Thread 1 is doing job
Thread 4 is doing job
Thread 5 is doing job
Thread 6 is doing job
Thread 7 is doing job
Thread 8 is doing job
Thread 9 is doing job
但实际上, 输出常常是混乱的:
Thread Thread 0 is doing job
Thread 2 is doing job
1 is doing job
Thread 3 is doing job
Thread 4 is doing job
Thread 5 is doing job
Thread 6 is doing job
Thread 7 is doing job
Thread 9 is doing job
Thread 8 is doing job
这种混乱会使输出难以使用.
2. 原因解析
2.1 全局资源共享和原子操作
-
std::cout
是全局标准输出流, 多个线程无序访问时会导致内容交错. -
虽然
std::cout
保证单次操作的原子性, 例如:// Thread A std::cout << "Thread A\n"; // Thread B std::cout << "Thread B\n";
可能输出为:
thread A thread B
或者:
thread B thread A
绝不会出现内容叠加在一起的情况, 比如这种:
thread thread A B
但如果多个操作组合在一起, 例如:
std::cout << "Thread " << id << " is doing job\n";
输出可能会交错, 导致不可读的结果.
2.2 输出混乱的影响
- 难以调试: 多线程调试信息混乱, 增加了定位问题的难度.
- 日志不可用: 实时系统中的日志输出可能会出现乱码, 导致信息丢失.
3. std::osyncstream
介绍
C++20 推出了同步输出流 std::osyncstream
, 用于解决上述问题.
3.1 基础原理
std::osyncstream
通过内置缓冲区, 在操作完成后一次性写入目标流, 从而保证输出内容的完整性和顺序. 每个线程有独立的缓冲区, 避免了线程间竞争.
3.2 用法示例
#include <iostream>
#include <syncstream> // 引入对应头文件
#include <thread>
#include <vector>
int main() {
constexpr int num_thread = 10;
std::vector<std::thread> threads;
// 开启线程
for (int i = 0; i < num_thread; i++) {
threads.emplace_back(
[](int id) {
std::osyncstream(std::cout) << "Thread " << id << " is doing job\n";
},
i);
}
// 等待线程结束
for (auto& t : threads) {
t.join();
}
return 0;
}
输出可以保证不会交错:
Thread 0 is doing job
Thread 3 is doing job
Thread 4 is doing job
Thread 7 is doing job
Thread 5 is doing job
Thread 1 is doing job
Thread 2 is doing job
Thread 9 is doing job
Thread 8 is doing job
Thread 6 is doing job
4. 优势和注意事项
4.1 优势
- 线程安全: 每个线程独立缓冲, 避免竞争.
- 完整性: 确保每次输出操作的内容完整无误.
- 易用性: 不需要显式加锁, 简化了代码.
- 兼容性: 支持主流 C++20 编译器(GCC 10+, Clang 12+, MSVC 19.28+).
4.2 注意事项
- 性能开销: 由于使用了缓冲区和锁, 性能可能略有下降.
- C++20 要求: 需要支持 C++20 标准的环境.
5. 总结
std::osyncstream
是 C++20 中一个重要的新特性, 通过引入线程安全的同步输出流, 解决了多线程环境下输出混乱的问题. 其实现简单高效, 适合在多线程日志, 调试输出等场景中广泛应用. 在实际项目中, 选择合适的工具和技术, 可以显著提升系统的稳定性和可维护性.