Skip to content

Commit

Permalink
1. 修改赞助链接
Browse files Browse the repository at this point in the history
2. 为第五章部分内容加粗
3. 修改线程池内容,增加更多的测试与描述
  • Loading branch information
Mq-b committed Aug 2, 2024
1 parent 3078c28 commit f2d31f4
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 7 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

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

[捐赠](/image/捐赠)[issues](https://github.com/Mq-b/ModernCpp-ConcurrentProgramming-Tutorial/issues)[pr](https://github.com/Mq-b/ModernCpp-ConcurrentProgramming-Tutorial/pulls) 均会在致谢列表中**铭记您的贡献**
[捐赠](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) 均会在致谢列表中**铭记您的贡献**

</div>

Expand Down
2 changes: 1 addition & 1 deletion md/05内存模型与原子操作.md
Original file line number Diff line number Diff line change
Expand Up @@ -666,7 +666,7 @@ void wake_up(){

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

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

那有没有可能:

Expand Down
34 changes: 29 additions & 5 deletions md/详细分析/04线程池.md
Original file line number Diff line number Diff line change
Expand Up @@ -425,22 +425,22 @@ int print_task2(int n) {
}

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

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

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

pool.start();
pool.start(); // 重新启动线程池

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

int sum = 0;
for(auto& future : futures){
Expand Down Expand Up @@ -477,7 +477,31 @@ Task 1 is running.
sum: 90
```

> 如果不自己显式调用 `join()` ,而是等待线程池对象调用析构函数,那么效果如同 `asio::thread_pool`,会先进行 `stop`,导致一些任务不执行。
> 如果不自己显式调用 `join()` ,而是等待线程池对象调用析构函数,那么效果如同 `asio::thread_pool`,会先进行 `stop`,导致一些任务无法执行。
它支持**任意可调用类型**,当然也包括非静态成员函数。我们使用了 [`std::decay_t`](https://zh.cppreference.com/w/cpp/types/decay),所以参数的传递其实是**按值复制**,而不是引用传递,这一点和大部分库的设计一致。示例如下:

```cpp
struct X{
void f(const int& n)const{
std::cout << &n << '\n';
}
};

X x;
int n = 6;
std::cout << &n << '\n';
pool.start();
pool.submit(&X::f, &x, n); // 默认复制,地址不同
pool.submit(&X::f, &x, std::ref(n));
pool.join();
```

> [运行](https://godbolt.org/z/vTc7M8Kov)测试。
我们的线程池的 `submit` 成员函数在传递参数的行为上,与先前介绍的 `std::thread``std::async` 等设施基本一致。

我们稍微介绍线程池的接口:

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

Expand Down

0 comments on commit f2d31f4

Please sign in to comment.