Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

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‎

Lines changed: 1 addition & 1 deletion
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‎

Lines changed: 1 addition & 1 deletion
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‎

Lines changed: 29 additions & 5 deletions
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)

AltStyle によって変換されたページ (->オリジナル) /