Skip to content

Commit 66b6edb

Browse files
committed
补充 std::cout 多线程输出交错的说明与改进方式
1 parent 1496935 commit 66b6edb

File tree

1 file changed

+13
-3
lines changed

1 file changed

+13
-3
lines changed

docs/cpp_tricks.md

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# 应知应会 C++ 小技巧
22

3-
[TOC]
3+
[toc]
44

55
## 交换两个变量
66

@@ -1029,6 +1029,8 @@ cout << '\n';
10291029

10301030
> {{ icon.fun }} 而是分子了 :)
10311031
1032+
`std::cout``operator<<` 调用是线程安全的,不会被打断,但多个 `operator<<` 的调用在多线程环境中可能会 **交错** ,导致输出结果混乱
1033+
10321034
他们中间可能穿插了其他线程的 cout,从而导致你 `"the answer is"` 打印完后,被其他线程的 `'\n'` 插入进来,导致换行混乱。
10331035

10341036
> {{ icon.tip }} 更多细节请看我们的 [多线程专题](threading.md)
@@ -1047,9 +1049,17 @@ cout << oss.str();
10471049
cout << std::format("the answer is {}\n", 42);
10481050
```
10491051

1050-
总之,就是要让 `operator<<` 只有一次。
1052+
总之,就是要让 `operator<<` 只有一次,自然就是没有交错。
1053+
1054+
如果可以使用 C++20,就可改用 `std::osyncstream{ std::cout }` :
1055+
1056+
```cpp
1057+
std::osyncstream{ std::cout } << "the answer is " << 42 << '\n';
1058+
```
1059+
1060+
`std::osyncstream` 提供保证:所有对最终目标缓冲区(上例中是 [std::cout](https://zh.cppreference.com/w/cpp/io/cout "cpp/io/cout"))作出的输出将免除数据竞争,而且将不以任何方式穿插或截断。
10511061
1052-
建议各位升级到 C++23,然后改用 `std::println`
1062+
如果可以使用 C++23,就可改用 `std::println` :
10531063
10541064
```cpp
10551065
std::println("the answer is {}", 42);

0 commit comments

Comments
 (0)