Skip to content

Commit 8db42b3

Browse files
committed
修改第四章条件变量的 wait 成员函数与 latch 的部分描述
1 parent 2920a99 commit 8db42b3

File tree

1 file changed

+17
-2
lines changed

1 file changed

+17
-2
lines changed

Diff for: md/04同步操作.md

+17-2
Original file line numberDiff line numberDiff line change
@@ -125,10 +125,25 @@ while (!pred())
125125
wait(lock);
126126
```
127127

128-
这可以避免“[虚假唤醒(spurious wakeup)](https://en.wikipedia.org/wiki/Spurious_wakeup)”。
128+
第二个版本只是对第一个版本的**包装**,等待并判断谓词,会调用第一个版本的重载。这可以避免“[虚假唤醒(spurious wakeup)](https://en.wikipedia.org/wiki/Spurious_wakeup)”。
129129

130130
> 条件变量虚假唤醒是指在使用条件变量进行线程同步时,有时候线程可能会在没有收到通知的情况下被唤醒。问题取决于程序和系统的具体实现。解决方法很简单,在循环中等待并判断条件可一并解决。使用 C++ 标准库则没有这个烦恼了。
131131
132+
我们也可以简单看一下 MSVC STL 的[源码实现](https://github.com/microsoft/STL/blob/22a8826/stl/inc/mutex#L555-L565)
133+
134+
```cpp
135+
void wait(unique_lock<mutex>& _Lck) noexcept {
136+
_Cnd_wait(_Mycnd(), _Lck.mutex()->_Mymtx());
137+
}
138+
139+
template <class _Predicate>
140+
void wait(unique_lock<mutex>& _Lck, _Predicate _Pred) {
141+
while (!_Pred()) {
142+
wait(_Lck);
143+
}
144+
}
145+
```
146+
132147
## 线程安全的队列
133148
134149
在本节中,我们介绍了一个更为复杂的示例,以巩固我们对条件变量的学习。为了实现一个线程安全的队列,我们需要考虑以下两个关键点:
@@ -1328,7 +1343,7 @@ int main() {
13281343
13291344
### `std::latch`
13301345
1331-
闩”,这个字其实个人觉得是不常见,“**门闩**” 是指门背后用来关门的棍子。好了好了,不用在意,在 C++ 中就是先前说的:*单次使用的线程屏障*
1346+
**” ,中文语境一般说“*门闩*” 是指门背后用来关门的棍子。不过不用在意,在 C++ 中的意思就是先前说的:***单次使用的线程屏障***
13321347
13331348
`latch` 类维护着一个 [`std::ptrdiff_t`](https://zh.cppreference.com/w/cpp/types/ptrdiff_t) 类型的计数[^6],且只能**减少**计数,**无法增加计数**。在创建对象的时候初始化计数器的值。线程可以阻塞,直到 latch 对象的计数减少到零。由于无法增加计数,这使得 `latch` 成为一种**单次使用的屏障**
13341349

0 commit comments

Comments
 (0)