Skip to content

Commit

Permalink
修改 std::barrier 的内容,强调其函数对象必须是不抛出异常的 #12
Browse files Browse the repository at this point in the history
  • Loading branch information
Mq-b committed Jun 10, 2024
1 parent 81d5fb5 commit 639e052
Showing 1 changed file with 19 additions and 0 deletions.
19 changes: 19 additions & 0 deletions md/04同步操作.md
Original file line number Diff line number Diff line change
Expand Up @@ -1376,6 +1376,15 @@ int main() {

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

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

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

---

最后请注意,我们的 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)

```cpp
std::barrier barrier{ 1,[] {} };
```
按照标准规定,这行代码会产生一个**编译错误**。因为传入的函数对象它不是 `noexcept` 的。不过,在 gcc 与 clang(即 libstdc++ 和 libc++)均可以通过编译,这是因为它们没有进行相应的检测,**存在缺陷**,为了代码的可维护性开发者应遵守标准规定,确保传入的函数对象是 `noexcept` 的。
## 总结
在并发编程中,同步操作对于并发编程至关重要。如果没有同步,线程基本上就是独立的,因其任务之间的相关性,才可作为一个整体执行(比如第二章的并行求和)。本章讨论了多种用于同步操作的工具,包括条件变量、future、promise、package_task、信号量。同时,详细介绍了 C++ 时间库的知识,以使用并发支持库中的“限时等待”。还使用 CMake + Qt 构建了一个带有 UI 界面的示例,展示异步**多线程的必要性**。最后介绍了 C++20 引入的两种新的并发设施,信号量、闩与屏障。
Expand Down

0 comments on commit 639e052

Please sign in to comment.