c++ - Windows XP 中来自 std::async 的 std::async
问题描述
此示例在 windows7 和 ideone.com 下打印所有 2 条消息,但无法在 windows xp 上打印第二条消息。我做错了什么?如果是错误,我应该在哪里报告?
使用 Visual Studio 2017 平台工具集 v141_xp 为 windows xp 编译。
#include <iostream>
#include <future>
#include <thread>
using namespace std;
int main()
{
auto f1 = async(launch::async, []()->int {
cout << "in outer async" << endl;
auto f2 = async(launch::async, []()->int {
cout << "in inner async" << endl;
return 2;
});
f2.get();
return 1;
});
f1.get();
return 0;
}
使用 std::thread 而不是 std::async 作为内部函数时的 UPD - 它在两个系统上都运行良好
auto f2 = thread([]()->int {
cout << "in inner async" << endl;
return 2;
});
f2.join();
UPD2
Visual Studio 2017 cl.exe 版本 19.14.26428 工具集 v141_xp
命令行:
/permissive- /Yu"stdafx.h" /GS /GL /analyze- /Wall /Gy /Zc:wchar_t /Zi /Gm- /O2 /sdl /Fd"Release\vc141.pdb" /Zc:inline /fp:precise /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_USING_V110_SDK71_" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /Gd /Oy- /Oi /MD /std:c++17 /FC /Fa"Release\" /EHsc /nologo /Fo"Release\" /Fp"Release\testasync.pch" /diagnostics:classic
在 windows xp 上使用时,UPD3 看起来像 launch::async 被忽略
vector<future<void>> v;
for( int i = 0; i < 10; i++ )
v.push_back(async(launch::async, []() {cout << "thread" << endl; this_thread::sleep_for(5s); }));
for( auto &f : v )
f.get();
在 windows7 上这需要大约 6 秒才能完成,在 windows xp 上大约需要 50 秒
解决方案
在 Windowsstd::async(...)
上位于线程池之上。所以可能会出现死锁。在里面f1
你运行新任务并调用f2.get()
,它会阻塞直到f2
完成。但是如果auto f2 = async(...)
选择了运行的同一个线程f1
,那么你就有死锁,你的程序不应该完成。如果是这样,那么情况并非如此。
更新
请阅读std::async
此处的 Microsoft 实施。它说:
C++ 标准规定,如果策略是 launch::async,则函数会创建一个新线程。但是,Microsoft 实施目前不符合要求。它从 Windows ThreadPool 中获取其线程,在某些情况下它可能会提供一个回收的线程而不是一个新的线程。这意味着 launch::async 策略实际上实现为 launch::async|launch::deferred
还有另一个答案,它揭示了微软std::async
实现的一个特殊功能:
- 它限制了它使用的后台线程总数,之后对 std::async 的调用将阻塞,直到线程空闲。在我的机器上,这个数字是 768。
所以,我假设,如果你在 ThreadPool 中只有一个线程,那么std::async
从任务内部调用将死锁。考虑到您的UPD3 ,可能是您的情况。
我真的建议阅读上面提到的答案,这样你就可以理解为什么微软的std::async
不同以及如何正确使用它。
推荐阅读
- scala - 如何在 collect 函数中创建 listBuffer
- verilog - 模拟中的 Xilinx FIFO IP 模块输出
- google-cloud-automl - 在 CSV 行中找不到 URI - AutoML NL 的导入错误
- c# - 如何逐行读取文件并打印到文本框c#
- dart - 为什么flutter中的open_file没有打开我的应用程序中的任何文件?
- javascript - 如何检测使用 window.open() 打开的窗口关闭事件
- javascript - 使用 underscore.js 返回子值最大的数组索引
- android - 在相对布局中向芯片组添加水平滚动
- javafx-11 - 在 Apache Netbeans 10 中创建 JavaFX11 应用程序时出错
- php - 简单的 PHP 重定向脚本不起作用。特别来自 geoplugin.net。有什么建议吗?