Skip to content

Commit 5e9c330

Browse files
committed
see changkun#2: add atomic
1 parent 5aff35b commit 5e9c330

File tree

2 files changed

+53
-1
lines changed

2 files changed

+53
-1
lines changed

book/zh-cn/07-thread.md

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ int main() {
194194
auto consumer = [&]() {
195195
while (true) {
196196
std::unique_lock<std::mutex> lock(mtx);
197-
while (!notified) { // avoid spurious wakeup
197+
while (!notified) { // 避免虚假唤醒
198198
cv.wait(lock);
199199
}
200200
// 短暂取消锁,使得生产者有机会在消费者消费空前继续生产
@@ -230,7 +230,36 @@ int main() {
230230

231231
## 7.5 原子操作与内存一致性
232232

233+
细心的读者可能会对前一小节中生产者消费者模型的例子可能存在编译器优化导致程序出错的情况产生疑惑。
234+
例如,布尔值 `notified` 没有被 `volatile` 修饰,编译器可能对此变量存在优化,例如将其作为一个寄存器的值,
235+
从而导致消费者线程永远无法观察到此值的变化。这是一个好问题,为了解释清楚这个问题,我们需要进一步讨论
236+
从 C++ 11 起引入的内存模型这一概念。我们首先来看一个问题,下面这段代码输出结果是多少?
233237

238+
```cpp
239+
#include <thread>
240+
#include <iostream>
241+
242+
int main() {
243+
int a = 0;
244+
volatile int flag = 0;
245+
246+
std::thread t1([&]() {
247+
while (flag != 1);
248+
249+
int b = a;
250+
std::cout << "b = " << b << std::endl;
251+
});
252+
253+
std::thread t2([&]() {
254+
a = 5;
255+
flag = 1;
256+
});
257+
258+
t1.join();
259+
t2.join();
260+
return 0;
261+
}
262+
```
234263

235264
## 7.6 事务内存
236265

code/7/7.6.atomic.pro.con.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#include <thread>
2+
#include <iostream>
3+
4+
int main() {
5+
int a = 0;
6+
volatile int flag = 0;
7+
8+
std::thread t1([&]() {
9+
while (flag != 1);
10+
11+
int b = a;
12+
std::cout << "b = " << b << std::endl;
13+
});
14+
15+
std::thread t2([&]() {
16+
a = 5;
17+
flag = 1;
18+
});
19+
20+
t1.join();
21+
t2.join();
22+
return 0;
23+
}

0 commit comments

Comments
 (0)