Skip to content

Commit f2d31f4

Browse files
committed
1. 修改赞助链接
2. 为第五章部分内容加粗 3. 修改线程池内容,增加更多的测试与描述
1 parent 3078c28 commit f2d31f4

File tree

3 files changed

+31
-7
lines changed

3 files changed

+31
-7
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
不管是否购买课程,任何组织和个人遵守 [CC BY-NC-ND 4.0](https://creativecommons.org/licenses/by-nc-nd/4.0/deed.zh-hans) 协议均可随意使用学习。
1212

13-
[捐赠](/image/捐赠)[issues](https://github.com/Mq-b/ModernCpp-ConcurrentProgramming-Tutorial/issues)[pr](https://github.com/Mq-b/ModernCpp-ConcurrentProgramming-Tutorial/pulls) 均会在致谢列表中**铭记您的贡献**
13+
[捐赠](https://github.com/Mq-b/ModernCpp-ConcurrentProgramming-Tutorial/tree/main/image/%E6%8D%90%E8%B5%A0)[issues](https://github.com/Mq-b/ModernCpp-ConcurrentProgramming-Tutorial/issues)[pr](https://github.com/Mq-b/ModernCpp-ConcurrentProgramming-Tutorial/pulls) 均会在致谢列表中**铭记您的贡献**
1414

1515
</div>
1616

md/05内存模型与原子操作.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -666,7 +666,7 @@ void wake_up(){
666666

667667
你们可能还有疑问:“**单线程能不能指令重排**?”
668668

669-
CPU 的指令重排必须遵循一定的规则,以确保程序的可观察副作用不受影响。对于单线程程序,CPU 会保证外部行为的一致性。对于多线程程序,需要开发者使用同步原语来显式地控制内存操作的顺序和可见性,确保多线程环境下的正确性。而标准库中提供的原子对象的原子操作,还可以设置内存次序。
669+
CPU 的指令重排必须遵循一定的规则,以确保程序的**可观察副作用**不受影响。对于单线程程序,CPU 会保证外部行为的一致性。对于多线程程序,需要开发者使用同步原语来显式地控制内存操作的顺序和可见性,确保多线程环境下的正确性。而标准库中提供的原子对象的原子操作,还可以设置内存次序。
670670

671671
那有没有可能:
672672

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

+29-5
Original file line numberDiff line numberDiff line change
@@ -425,22 +425,22 @@ int print_task2(int n) {
425425
}
426426

427427
int main() {
428-
ThreadPool pool{ 4 }; // 创建一个有 4 个线程的线程池
428+
ThreadPool pool{ 4 }; // 创建一个有 4 个线程的线程池 构造函数自动启动线程池
429429
std::vector<std::future<int>> futures; // future 集合,获取返回值
430430

431431
for (int i = 0; i < 10; ++i) {
432432
futures.emplace_back(pool.submit(print_task, i));
433433
}
434-
pool.join();
434+
pool.join(); // 阻塞,让任务全部执行完毕
435435

436436
std::puts("---------------------");
437437

438-
pool.start();
438+
pool.start(); // 重新启动线程池
439439

440440
for (int i = 0; i < 10; ++i) {
441441
futures.emplace_back(pool.submit(print_task2, i));
442442
}
443-
pool.join();
443+
pool.join(); // 阻塞,让任务全部执行完毕
444444

445445
int sum = 0;
446446
for(auto& future : futures){
@@ -477,7 +477,31 @@ Task 1 is running.
477477
sum: 90
478478
```
479479

480-
> 如果不自己显式调用 `join()` ,而是等待线程池对象调用析构函数,那么效果如同 `asio::thread_pool`,会先进行 `stop`,导致一些任务不执行。
480+
> 如果不自己显式调用 `join()` ,而是等待线程池对象调用析构函数,那么效果如同 `asio::thread_pool`,会先进行 `stop`,导致一些任务无法执行。
481+
482+
它支持**任意可调用类型**,当然也包括非静态成员函数。我们使用了 [`std::decay_t`](https://zh.cppreference.com/w/cpp/types/decay),所以参数的传递其实是**按值复制**,而不是引用传递,这一点和大部分库的设计一致。示例如下:
483+
484+
```cpp
485+
struct X{
486+
void f(const int& n)const{
487+
std::cout << &n << '\n';
488+
}
489+
};
490+
491+
X x;
492+
int n = 6;
493+
std::cout << &n << '\n';
494+
pool.start();
495+
pool.submit(&X::f, &x, n); // 默认复制,地址不同
496+
pool.submit(&X::f, &x, std::ref(n));
497+
pool.join();
498+
```
499+
500+
> [运行](https://godbolt.org/z/vTc7M8Kov)测试。
501+
502+
我们的线程池的 `submit` 成员函数在传递参数的行为上,与先前介绍的 `std::thread``std::async` 等设施基本一致。
503+
504+
我们稍微介绍线程池的接口:
481505

482506
**构造函数和析构函数:**
483507

0 commit comments

Comments
 (0)