问题标签 [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.

0 投票
1 回答
2512 浏览

c++ - 使用线程池的 std::async 的 Visual C++ 实现是否合法

Visual C ++CreateThreadpoolWorkQueueUserWorkItem使用std::async.std::launch::async

池中的线程数是有限的。如果创建多个长时间运行而不休眠的任务(包括做 I/O),队列中即将到来的任务将没有机会工作。

标准(我使用 N4140)说使用std::asyncwithstd::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::threads,它们都执行一些非常长的(可能是无限的)任务,它们都会被安排(至少在 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 则不会。


类似的问题:

0 投票
1 回答
3303 浏览

multithreading - c++11 线程 vs 异步

考虑以下两个我尝试启动 10000 个线程的代码片段:

片段 1

片段 2

第一种情况总是成功。即我能够创建 10000 个线程,然后我必须等待所有线程完成。在第二种情况下,我几乎总是在创建 1600 多个线程后最终得到一个异常(“资源不可用再试一次”)。

使用 std::launch::async 的启动策略,我认为这两个片段的行为方式应该相同。具有异步启动策略的 std::async 与使用 std::thread 显式启动线程有何不同?

我在 Windows 10 VS2015 上,二进制文件是在 x86 发布模式下构建的。

0 投票
1 回答
148 浏览

c++ - VS2015 std::async 奇怪

在 VS2015 的以下代码中,我进入acefbd了第一行,这是正确的。但在第二次测试中,我将其分成单独的行,输出为abcdef.

这是预期的行为吗?

0 投票
0 回答
188 浏览

c++ - boost::async() 的异常丢失类型

升压版本:1.61,GCC 版本 6.2.0,C++14

调用中的异常boost::async()似乎丢失了它们的类型,而它与std::async. std::asyncboost::async我失踪之间有根本区别吗?

以下代码有效(使用std::async):

和输出

但是,以下代码(它是相同的,只是使用boost::async而不是std::async)没有按预期工作:

它输出:

它也不适用于boost::future::then延续:

输出:

因此,当跨越线程边界时,异常的具体类型似乎丢失了。但是,它似乎没有连接到线程,因为根据我的测试,对于std::launch::deferred(工作正常)和boost::launch::deferred(丢失异常类型)也是如此。

0 投票
1 回答
74 浏览

multithreading - 在抽象基类中使用 c++11 的 std::async

为什么不让这样的线程在抽象基类中工作?我试图为从这个基类派生的用户抽象出所有的多线程细节。callbackSquare当我清楚地写出返回 type时,我不明白为什么它说“没有名为'type'的类型” int

我得到的奇怪错误是:

0 投票
1 回答
678 浏览

multithreading - 如何在不使用 std::atomic_bool 的情况下提前终止 std::async 线程?

我有一个接受回调的函数,并用它来处理 10 个单独的线程。但是,通常情况下并非所有工作都需要。例如,如果在第三个线程上获得了所需的结果,它应该停止对剩余活动线程进行的所有工作。

这里的这个答案表明,除非你让回调函数接受一个额外的参数,否则这是不可能的,std::atomic_bool这表明函数是否应该提前终止。

这个解决方案对我不起作用。工人在一个基类中旋转,这个基类的重点是抽象出多线程的细节。我怎样才能做到这一点?我预计我将不得不放弃std::async更多涉及的事情。

0 投票
1 回答
145 浏览

c++ - 为什么使用 openMP 的 VC++ 矩阵时间向量比异步更快?

我用两种方法对向量乘以矩阵进行编码,一种使用 openMP,另一种使用 std::async。我预计性能几乎相同。OpenMP 在第一次调用时很慢,可能是因为它推迟了创建线程池。之后,异步版本始终慢 40%。(我有英特尔酷睿 i5,它是 4 个核心。)

这是怎么回事?VC++ 不使用线程池进行异步吗?我在做傻事吗?(最有可能。)我认为对输出向量的访问间隔足够大,以避免错误共享。

0 投票
2 回答
155 浏览

c++ - shared_ptr 的 use_count() 在 gcc 4.6.3 中移入 std::async

在下面的代码中,我希望移入use_count()的是:shared_ptrstd::async1


我的平台使用 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 升级我的编译器?

0 投票
2 回答
220 浏览

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::asyncs 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::asyncs. 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)?

0 投票
1 回答
596 浏览

c++11 - 标准::原子和拉姆达

有谁知道为什么这个程序进入无限循环,而不是在 5 秒左右后停止?

最新的 gcc 和 clang 编译器都会发生这种情况;是否atomic_bool遭受与向量相同的问题bool

如果我使用atomic<int>它可以正常工作。