问题标签 [stdasync]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c++ - 使用线程池的 std::async 的 Visual C++ 实现是否合法
Visual C ++CreateThreadpoolWork
在QueueUserWorkItem
使用std::async
.std::launch::async
池中的线程数是有限的。如果创建多个长时间运行而不休眠的任务(包括做 I/O),队列中即将到来的任务将没有机会工作。
标准(我使用 N4140)说使用std::async
withstd::launch::async
...调用
INVOKE(DECAY_COPY(std::forward<F>(f)), DECAY_COPY(std::forward<Args>(args))...)
(20.9.2, 30.3.1.2)就像在一个由线程对象表示的新执行DECAY_COPY()
线程中一样,调用async
.
(§30.6.8p3,强调我的。)
std::thread
的构造函数创建一个新线程等。
关于一般线程它说(§1.10p3):
实现应该确保所有未阻塞的线程最终都会取得进展。[注意:标准库函数可能会静默阻塞 I/O 或锁定。执行环境中的因素,包括外部强加的线程优先级,可能会阻止实现对前进进度做出某些保证。——<em>尾注]
如果我创建一堆 OS 线程或std::thread
s,它们都执行一些非常长的(可能是无限的)任务,它们都会被安排(至少在 Windows 上;不会弄乱优先级、亲缘关系等)。如果我们将相同的任务调度到 Windows 线程池(或使用std::async(std::launch::async, ...)
哪个线程池),那么在较早的任务完成之前,稍后的调度任务将不会运行。
严格来说,这合法吗?“最终”是什么意思?
问题是,如果首先安排的任务实际上是无限的,那么其余的任务将不会运行。所以其他线程(不是操作系统线程,而是根据 as-if 规则的“C++ 线程”)不会取得进展。
有人可能会争辩说,如果代码具有无限循环,则行为是未定义的,因此它是合法的。
但我认为,我们不需要标准所说的那种有问题的无限循环会导致 UB 实现这一点。访问 volatile 对象、执行原子操作和同步操作都是“禁用”关于循环终止的假设的副作用。
(我有一堆异步调用执行以下 lambda
并且仅在用户输入时才释放锁定。但是还有其他有效类型的合法无限循环。)
如果我安排了几个这样的任务,我安排在他们之后的任务就不会运行。
一个非常邪恶的例子是启动太多任务,这些任务在释放锁/引发标志之前一直运行,然后使用 `std::async(std::launch::async, ...) 调度引发标志的任务. 除非“最终”这个词意味着非常令人惊讶的东西,否则这个程序必须终止。但是在 VC++ 实现下它不会!
在我看来,这似乎违反了标准。让我想知道的是笔记中的第二句话。一些因素可能会阻止实现对前进的进展做出某些保证。那么这些实现如何符合要求呢?
这就像说可能有一些因素阻止实现提供内存排序、原子性甚至多个执行线程的存在的某些方面。很好,但符合要求的托管实现必须支持多线程。对他们和他们的因素来说太糟糕了。如果他们不能提供他们那不是 C++。
这是放宽要求吗?如果这样解释,则完全撤销了该要求,因为它没有指定因素是什么,更重要的是,实现可能不提供哪些保证。
如果不是——那张纸条甚至意味着什么?
我记得根据 ISO/IEC 指令,脚注是非规范性的,但我不确定注释。我确实在 ISO/IEC 指令中找到了以下内容:
24 个音符
24.1 目的或理由
注释用于提供旨在帮助理解或使用文档文本的附加信息。该文件应可以在没有注释的情况下使用。
强调我的。如果我考虑没有那个不清楚的注释的文档,在我看来,线程必须取得进展,std::async(std::launch::async, ...)
效果好像仿函数是在一个新线程上执行的,好像它是使用创建的std::thread
,因此使用std::async(std::launch::async, ...)
must调度仿函数取得进展。在使用线程池的 VC++ 实现中,它们没有。所以VC++在这方面是违反标准的。
完整示例,在 i5-6440HQ 上的 Windows 10 Enterprise 1607 上使用 VS 2015U3 进行测试:
4个或更少它终止。超过 4 则不会。
类似的问题:
是否有使用线程池的 std::async 实现?- 但它不质疑合法性,也没有答案。
std::async - 依赖于实现的用法?- 提到“线程池并不真正受支持”,但侧重于
thread_local
变量(即使答案和评论所说的“不简单”或非平凡也是可以解决的)并且没有解决接近取得进展的要求的注释。
multithreading - c++11 线程 vs 异步
考虑以下两个我尝试启动 10000 个线程的代码片段:
片段 1
片段 2
第一种情况总是成功。即我能够创建 10000 个线程,然后我必须等待所有线程完成。在第二种情况下,我几乎总是在创建 1600 多个线程后最终得到一个异常(“资源不可用再试一次”)。
使用 std::launch::async 的启动策略,我认为这两个片段的行为方式应该相同。具有异步启动策略的 std::async 与使用 std::thread 显式启动线程有何不同?
我在 Windows 10 VS2015 上,二进制文件是在 x86 发布模式下构建的。
c++ - VS2015 std::async 奇怪
在 VS2015 的以下代码中,我进入acefbd
了第一行,这是正确的。但在第二次测试中,我将其分成单独的行,输出为abcdef
.
这是预期的行为吗?
c++ - boost::async() 的异常丢失类型
升压版本:1.61,GCC 版本 6.2.0,C++14
调用中的异常boost::async()
似乎丢失了它们的类型,而它与std::async
. std::async
和boost::async
我失踪之间有根本区别吗?
以下代码有效(使用std::async
):
和输出
但是,以下代码(它是相同的,只是使用boost::async
而不是std::async
)没有按预期工作:
它输出:
它也不适用于boost::future::then
延续:
输出:
因此,当跨越线程边界时,异常的具体类型似乎丢失了。但是,它似乎没有连接到线程,因为根据我的测试,对于std::launch::deferred
(工作正常)和boost::launch::deferred
(丢失异常类型)也是如此。
multithreading - 在抽象基类中使用 c++11 的 std::async
为什么不让这样的线程在抽象基类中工作?我试图为从这个基类派生的用户抽象出所有的多线程细节。callbackSquare
当我清楚地写出返回 type时,我不明白为什么它说“没有名为'type'的类型” int
。
我得到的奇怪错误是:
multithreading - 如何在不使用 std::atomic_bool 的情况下提前终止 std::async 线程?
我有一个接受回调的函数,并用它来处理 10 个单独的线程。但是,通常情况下并非所有工作都需要。例如,如果在第三个线程上获得了所需的结果,它应该停止对剩余活动线程进行的所有工作。
这里的这个答案表明,除非你让回调函数接受一个额外的参数,否则这是不可能的,std::atomic_bool
这表明函数是否应该提前终止。
这个解决方案对我不起作用。工人在一个基类中旋转,这个基类的重点是抽象出多线程的细节。我怎样才能做到这一点?我预计我将不得不放弃std::async
更多涉及的事情。
c++ - 为什么使用 openMP 的 VC++ 矩阵时间向量比异步更快?
我用两种方法对向量乘以矩阵进行编码,一种使用 openMP,另一种使用 std::async。我预计性能几乎相同。OpenMP 在第一次调用时很慢,可能是因为它推迟了创建线程池。之后,异步版本始终慢 40%。(我有英特尔酷睿 i5,它是 4 个核心。)
这是怎么回事?VC++ 不使用线程池进行异步吗?我在做傻事吗?(最有可能。)我认为对输出向量的访问间隔足够大,以避免错误共享。
c++ - shared_ptr 的 use_count() 在 gcc 4.6.3 中移入 std::async
在下面的代码中,我希望移入use_count()
的是:shared_ptr
std::async
1
我的平台使用 gcc 4.6.3,上面的代码给出了这个输出(fun: sp.use_count() == 2
):
在coliru.stacked-crooked.com 上,我得到了我想要的行为(fun: sp.use_count() == 1
):
我不确定 coliru 使用的是什么编译器,但我猜它比 gcc 4.6.3 更新。
是否有某种方法,一些解决方法,可以获得我想要的行为,而不必从 gcc 4.6.3 升级我的编译器?
c++ - Can long-running std::asyncs starve other std::asyncs?
As I understand it, usual implementations of std::async schedule these jobs on threads from a pre-allocated thread pool.
So lets say I first create and schedule enough long-running std::async
s to keep all threads from that thread pool occupied. Directly afterwards (before long they finished executing) I also create and schedule some short-running std::async
s. Could it happen that the short-running ones aren't executed at all until at least one of the long-running ones has finished? Or is there some guarantee in the standard (specifically C++11) that prevents this kind of situation (like spawning more threads so that the OS can schedule them in a round-robin fasion)?
c++11 - 标准::原子和拉姆达
有谁知道为什么这个程序进入无限循环,而不是在 5 秒左右后停止?
最新的 gcc 和 clang 编译器都会发生这种情况;是否atomic_bool
遭受与向量相同的问题bool
?
如果我使用atomic<int>
它可以正常工作。