Skip to content

Commit 639e052

Browse files
committed
修改 std::barrier 的内容,强调其函数对象必须是不抛出异常的 #12
1 parent 81d5fb5 commit 639e052

File tree

1 file changed

+19
-0
lines changed

1 file changed

+19
-0
lines changed

md/04同步操作.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1376,6 +1376,15 @@ int main() {
13761376

13771377
上节我们学习了 `std::latch` ,本节内容也不会对你构成难度。
13781378

1379+
```cpp
1380+
template< class CompletionFunction = /* 未指定 */ >
1381+
class barrier;
1382+
```
1383+
1384+
**CompletionFunction** - 函数对象类型。
1385+
1386+
---
1387+
13791388
[`std::barrier`](https://zh.cppreference.com/w/cpp/thread/barrier) 和 `std::latch` 最大的不同是,前者可以在阶段完成之后将计数重置为构造时传递的值,而后者只能减少计数。我们用一个非常简单直观的示例为你展示:
13801389
13811390
```cpp
@@ -1478,6 +1487,16 @@ int main(){
14781487

14791488
这样,`arrive_and_drop` 的作用就非常明显了,使用也十分的简单。
14801489

1490+
---
1491+
1492+
最后请注意,我们的 lambda 表达式必须声明为 `noexcept` ,因为 `std::barrier` 要求其**函数对象类型必须是不抛出异常的**。即要求 `std::is_nothrow_invocable_v<_Completion_function&>`**true**,见 [MSVC STL](https://github.com/microsoft/STL/blob/9ad382e/stl/inc/barrier#L75-L76)
1493+
1494+
```cpp
1495+
std::barrier barrier{ 1,[] {} };
1496+
```
1497+
1498+
按照标准规定,这行代码会产生一个**编译错误**。因为传入的函数对象它不是 `noexcept` 的。不过,在 gcc 与 clang(即 libstdc++ 和 libc++)均可以通过编译,这是因为它们没有进行相应的检测,**存在缺陷**,为了代码的可维护性开发者应遵守标准规定,确保传入的函数对象是 `noexcept` 的。
1499+
14811500
## 总结
14821501
14831502
在并发编程中,同步操作对于并发编程至关重要。如果没有同步,线程基本上就是独立的,因其任务之间的相关性,才可作为一个整体执行(比如第二章的并行求和)。本章讨论了多种用于同步操作的工具,包括条件变量、future、promise、package_task、信号量。同时,详细介绍了 C++ 时间库的知识,以使用并发支持库中的“限时等待”。还使用 CMake + Qt 构建了一个带有 UI 界面的示例,展示异步**多线程的必要性**。最后介绍了 C++20 引入的两种新的并发设施,信号量、闩与屏障。

0 commit comments

Comments
 (0)