Skip to content

Commit 3078c28

Browse files
committed
1. 修改用词“堵塞”->"阻塞"。
2. 稍微修改线程池一章中的部分描述。Mq-b#12 3. 修改捐赠页面。
1 parent 6eb34a0 commit 3078c28

File tree

4 files changed

+14
-14
lines changed

4 files changed

+14
-14
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828

2929
<div align="center">
3030

31-
![猫猫虫](/image/猫猫虫旋转.jpg)
31+
![猫猫虫](./image/猫猫虫旋转.jpg)
3232

3333
如果你觉得本仓库对你有所帮助,可以通过支付宝赞助白老师,激励白老师有更多的精力和信心维护本仓库。
3434

@@ -37,4 +37,4 @@
3737
> [!TIP]
3838
> 每一位开发者赞助 `30`,白老师一天的食品安全就有了着落。
3939
40-
![赞助](/image/赞助.jpg)
40+
<img src="./image/赞助.jpg" width=512px alt="cpp"/>

md/02使用线程.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ int main(){
3636

3737
`std::thread t{ hello };` 创建了一个线程对象 `t`,将 `hello` 作为它的[可调用(Callable)](https://zh.cppreference.com/w/cpp/named_req/Callable)对象,在新线程中执行。线程对象关联了一个线程资源,我们无需手动控制,在线程对象构造成功,就自动在新线程开始执行函数 `hello`
3838

39-
`t.join();` 等待线程对象 `t` 关联的线程执行完毕,否则将一直堵塞。这里的调用是必须的,否则 `std::thread` 的析构函数将调用 [`std::terminate()`](https://zh.cppreference.com/w/cpp/error/terminate) 无法正确析构。
39+
`t.join();` 等待线程对象 `t` 关联的线程执行完毕,否则将一直阻塞。这里的调用是必须的,否则 `std::thread` 的析构函数将调用 [`std::terminate()`](https://zh.cppreference.com/w/cpp/error/terminate) 无法正确析构。
4040

4141
这是因为我们创建线程对象 `t` 的时候就关联了一个活跃的线程,调用 `join()` 就是确保线程对象关联的线程已经执行完毕,然后会修改对象的状态,让 [`std::thread::joinable()`](https://zh.cppreference.com/w/cpp/thread/thread/joinable) 返回 `false`,表示线程对象目前没有关联活跃线程。`std::thread` 的析构函数,正是通过 `joinable()` 判断线程对象目前是否有关联活跃线程,如果为 `true`,那么就当做有关联活跃线程,会调用 `std::terminate()`
4242

@@ -291,7 +291,7 @@ my_thread.join();
291291

292292
认为这样可以确保被分离的线程在这里阻塞执行完?
293293

294-
我们前面聊的很清楚了,detach() 是线程分离,**线程对象放弃了线程资源的所有权**,此时我们的 my_thread 它现在根本没有关联任何线程。调用 join() 是:“阻塞当前线程直至 *this 所标识的线程结束其执行”,我们的**线程对象都没有线程,堵塞什么?执行什么呢?**
294+
我们前面聊的很清楚了,detach() 是线程分离,**线程对象放弃了线程资源的所有权**,此时我们的 my_thread 它现在根本没有关联任何线程。调用 join() 是:“阻塞当前线程直至 *this 所标识的线程结束其执行”,我们的**线程对象都没有线程,阻塞什么?执行什么呢?**
295295

296296
简单点说,必须是 std::thread 的 joinable() 为 true 即线程对象有活跃线程,才能调用 join() 和 detach()。
297297

@@ -691,7 +691,7 @@ int main() {
691691
}
692692
```
693693
694-
这段代码通过**移动构造**转移了线程对象 `t` 的线程资源所有权到 `t2`,这里虽然有两个 `std::thread` 对象,但是从始至终只有一个线程资源,让持有线程资源的 `t2` 对象最后调用 `join()` 堵塞让其线程执行完毕`t``t2` 都能正常析构。
694+
这段代码通过**移动构造**转移了线程对象 `t` 的线程资源所有权到 `t2`,这里虽然有两个 `std::thread` 对象,但是从始至终只有一个线程资源,让持有线程资源的 `t2` 对象最后调用 `join()` 阻塞让其线程执行完毕`t``t2` 都能正常析构。
695695
696696
我们还可以使用移动赋值来转移线程资源的所有权:
697697

md/04同步操作.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -446,14 +446,14 @@ int main(){
446446
447447
其实到此基本就差不多了,我们再介绍两个常见问题即可:
448448
449-
1. 如果从 `std::async` 获得的 [std::future](https://zh.cppreference.com/w/cpp/thread/future) 没有被移动或绑定到引用,那么在完整表达式结尾, [std::future](https://zh.cppreference.com/w/cpp/thread/future)**析构函数将阻塞到异步计算完成**。因为临时对象的生存期就在这一行,调用析构函数阻塞执行
449+
1. 如果从 `std::async` 获得的 [`std::future`](https://zh.cppreference.com/w/cpp/thread/future) 没有被移动或绑定到引用,那么在完整表达式结尾, `std::future`**[析构函数](https://zh.cppreference.com/w/cpp/thread/future/%7Efuture)将阻塞,直到到异步任务完成**。因为临时对象的生存期就在这一行,而对象生存期结束就会调用调用析构函数
450450
451451
```cpp
452452
std::async(std::launch::async, []{ f(); }); // 临时量的析构函数等待 f()
453453
std::async(std::launch::async, []{ g(); }); // f() 完成前不开始
454454
```
455455
456-
如你所见,这并不能创建异步任务,会堵塞,然后逐个执行。
456+
如你所见,这并不能创建异步任务,它会阻塞,然后逐个执行。
457457
458458
2. 被移动的 `std::future` 没有所有权,失去共享状态,不能调用 `get`、`wait` 成员函数。
459459
@@ -489,7 +489,7 @@ std::packaged_task<double(int, int)> task([](int a, int b){
489489
});
490490
std::future<double>future = task.get_future();
491491
task(10, 2); // 此处执行任务
492-
std::cout << future.get() << '\n'; // 不堵塞,此处获取返回值
492+
std::cout << future.get() << '\n'; // 不阻塞,此处获取返回值
493493
```
494494
495495
> [运行](https://godbolt.org/z/799Khvadc)测试。
@@ -505,7 +505,7 @@ std::thread t{ std::move(task),10,2 }; // 任务在线程中执行
505505
// todo.. 幻想还有许多耗时的代码
506506
t.join();
507507
508-
std::cout << future.get() << '\n'; // 并不堵塞,获取任务返回值罢了
508+
std::cout << future.get() << '\n'; // 并不阻塞,获取任务返回值罢了
509509
```
510510
511511
> [运行](https://godbolt.org/z/85r9db49z)测试。

md/详细分析/04线程池.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ graph TD
7272

7373
---
7474

75-
了解以上这些基础概念是第一步也是最后一步,随着水平的提升,对这些概念认知与理解也会逐渐提升
75+
了解以上这些基础概念是第一步也是最后一步,随着水平的提升,对这些概念的理解也会逐渐提升
7676

7777
## 市面上常见的线程池
7878

@@ -169,7 +169,7 @@ for (int i = 0; i < 10; ++i) {
169169

170170
> [运行](https://godbolt.org/z/haPqKb1h7)测试。
171171
172-
因为析构函数并不是堵塞执行完所有任务,而是先**停止**,再 `join()` 以及 `shutdown()`
172+
因为析构函数并不是阻塞直到执行完所有任务,而是先**停止**,再 `join()` 以及 `shutdown()`
173173

174174
`Boost.Asio` 提供的线程池使用十分简单,接口高度封装,几乎无需关心底层具体实现,易于使用。
175175

@@ -450,7 +450,7 @@ int main() {
450450
} // 析构自动 stop() join()
451451
```
452452
453-
**可能的[运行结果](https://godbolt.org/z/YT4ahh1Wz)**:
453+
**可能的[运行结果](https://godbolt.org/z/3rbExqbb7)**:
454454
455455
```shell
456456
Task 0 is running.
@@ -495,11 +495,11 @@ sum: 90
495495

496496
- **`start()`**:启动线程池,创建并启动指定数量的线程。
497497

498-
---
498+
我们并没有提供一个功能强大的所谓的“***调度器***”,我们只是利用条件变量和互斥量,让操作系统自行调度而已,它并不具备设置任务优先级之类的调度功能。
499499

500500
当然,你可能还希望我们的线程池具备更多功能或改进,比如控制任务优先级、设置最大线程数量、返回当前活跃线程数等。此外,异常处理也是一个值得考虑的方面。
501501

502-
有些功能实现起来非常简单,而有些则需要更多的思考和设计。不过,这些优化超出了本次讲解的范围。如果有兴趣,可以尝试自行优化我们提供的线程池实现。我们给出的线程池实现简单完善且直观,用来学习再好不过。
502+
有些功能实现起来非常简单,而有些则需要更多的思考和设计。不过,这些功能超出了本次讲解的范围。如果有兴趣,可以尝试自行优化我们提供的线程池实现,添加更多的功能。我们给出的线程池实现简单完善且直观,用来学习再好不过。
503503

504504
## 总结
505505

0 commit comments

Comments
 (0)