File tree Expand file tree Collapse file tree 2 files changed +21
-1
lines changed Expand file tree Collapse file tree 2 files changed +21
-1
lines changed Original file line number Diff line number Diff line change @@ -957,7 +957,7 @@ MSVC 无法使用 GCC 的编译器扩展,GCC 也肯定无法使用 MSVC 的扩
957
957
958
958
> ### 注意事项
959
959
>
960
- > 需要注意的是,在 MSVC 的实现中,`std::async` 策略为 [`launch::async`](https://zh.cppreference.com/w/cpp/thread/launch) 却并不是每次都创建一个新的线程 ,而是从线程池获取线程。**这意味着无法保证线程局部变量在任务完成时会被销毁**。如果线程被回收并用于新的 `std::async` 调用,则旧的线程局部变量仍然存在。因此,**建议不要将线程局部变量与 `std::async` 一起使用**。[文档](https://learn.microsoft.com/zh-cn/cpp/standard-library/future-functions?view=msvc-170)。
960
+ > 需要注意的是,在 MSVC 的实现中,如果 `std::async` 策略为 [`launch::async`](https://zh.cppreference.com/w/cpp/thread/launch) ,但却并不是每次都创建一个新的线程 ,而是从线程池获取线程。**这意味着无法保证线程局部变量在任务完成时会被销毁**。如果线程被回收并用于新的 `std::async` 调用,则旧的线程局部变量仍然存在。因此,**建议不要将线程局部变量与 `std::async` 一起使用**。[文档](https://learn.microsoft.com/zh-cn/cpp/standard-library/future-functions?view=msvc-170)。
961
961
>
962
962
> 虽然还没有讲 `std::async` ,不过还是可以注意一下这个问题,我们用一个简单的示例为你展示:
963
963
>
Original file line number Diff line number Diff line change @@ -387,6 +387,26 @@ int main(){
387
387
388
388
而我们先前一直没有写明这个参数,是因为 ` std::async ` 函数模板有两个** 重载** ,不给出执行策略就是以:` std::launch::async | std::launch::deferred ` 调用另一个重载版本(这一点中在[ 源码] ( https://github.com/microsoft/STL/blob/f54203f/stl/inc/future#L1425-L1430 ) 中很明显),此策略表示由实现选择到底是否创建线程执行异步任务。典型情况是,如果系统资源充足,并且异步任务的执行不会导致性能问题,那么系统可能会选择在新线程中执行任务。但是,如果系统资源有限,或者延迟执行可以提高性能或节省资源,那么系统可能会选择延迟执行。
389
389
390
+ > 然而值得注意的是,在 MSVC STL 的实现中,` launch::async | launch::deferred ` 与 ` launch::async ` 执行策略毫无区别,[ ** 源码** ] ( https://github.com/microsoft/STL/blob/f54203f/stl/inc/future#L1400-L1410 ) 如下:
391
+ >
392
+ > ``` cpp
393
+ > template <class _Ret , class _ Fty>
394
+ > _Associated_state<typename _P_arg_type<_Ret>::type>* _Get_associated_state (launch _ Psync, _ Fty&& _ Fnarg) {
395
+ > // construct associated asynchronous state object for the launch type
396
+ > switch (_Psync) { // select launch type
397
+ > case launch::deferred:
398
+ > return new _Deferred_async_state<_Ret>(_STD forward<_Fty>(_Fnarg));
399
+ > case launch::async: // TRANSITION, fixed in vMajorNext, should create a new thread here
400
+ > default:
401
+ > return new _Task_async_state<_Ret>(_STD forward<_Fty>(_Fnarg));
402
+ > }
403
+ > }
404
+ > ```
405
+ >
406
+ > 且 `_Task_async_state` 会通过 [`::Concurrency::create_task`](https://github.com/microsoft/STL/blob/f54203f/stl/inc/future#L663-L665) 从线程池中获取线程并执行任务返回包装对象。
407
+ >
408
+ > 简而言之,使用 `std::async`,只要不是 `launch::deferred` 策略,那么 MSVC STL 实现中都是必然在线程中执行任务。因为是线程池,所以执行新任务是否创建新线程,任务执行完毕线程是否立即销毁,***不确定***。
409
+
390
410
我们来展示一下:
391
411
392
412
```cpp
You can’t perform that action at this time.
0 commit comments