当未存储返回值时,std :: async不会生成新线程

时间:2020-12-01 20:56:47

Consider I have lamba foo which just does some stuff and doesn't need to return anything. When I do this:

考虑一下我有lamba foo,只做一些东西,不需要返回任何东西。我这样做的时候:

std::future<T> handle = std::async(std::launch::async, foo, arg1, arg2);

Everything runs fine and the lamba will be spawned in a new thread. However, when I don't store the std::future which the std::async returns, the foo will be run in the main thread and block it.

一切都运行正常,lamba将在一个新的线程中产生。但是,当我不存储std :: async返回的std :: future时,foo将在主线程中运行并阻塞它。

std::async(std::launch::async, foo, arg1, arg2);

What am I missing here?

我在这里想念的是什么?

3 个解决方案

#1


16  

From just::thread documentation:

来自just :: thread文档:

If policy is std::launch::async then runs INVOKE(fff,xyz...) on its own thread. The returned std::future will become ready when this thread is complete, and will hold either the return value or exception thrown by the function invocation. The destructor of the last future object associated with the asynchronous state of the returned std::future shall block until the future is ready.

如果策略是std :: launch :: async,则在其自己的线程上运行INVOKE(fff,xyz ...)。当此线程完成时,返回的std :: future将变为就绪状态,并将保存函数调用抛出的返回值或异常。与返回的std :: future的异步状态关联的最后一个对象的析构函数将阻塞,直到将来准备就绪。

In

std::async(std::launch::async, foo, arg1, arg2);

The returned future is not assigned anywhere and its destructor blocks until foo finishes.

返回的未来不会分配到任何地方,它的析构函数会阻塞,直到foo结束。

#2


4  

I would like to add a link to an article by Herb Sutter on async and ~future in which he argues that futures should never block.

我想添加一个链接到Herb Sutter关于async和〜future的文章,他认为期货永远不应该阻止。

#3


0  

Why blocking?

为什么阻止?

  1. std::async(); returns std::future temporary object
  2. 的std ::异步();返回std :: future临时对象
  3. temporary object is destroyed immediately, calling desctructor.
  4. 临时对象立即被销毁,调用析构函数。
  5. std::future destructor is blocking. It is bad and troublesome.
  6. std :: future析构函数正在阻塞。这很糟糕而且很麻烦。

Why assigning is ok?

为什么分配是好的?

By assigning to a variable, the returned object is not destroyed immediately, but later, until end of scope of your calling code.

通过赋值给变量,返回的对象不会立即被销毁,而是稍后销毁,直到调用代码范围结束。

Code Example: main1 is ok. main2 and main3 are equivalently blocking the main thread.

代码示例:main1没问题。 main2和main3等效地阻塞主线程。

void forever() {
    while (true);
}

void main1() {
    std::future<void> p = std::async(std::launch::async, forever);
    std::cout << "printing" << std::endl; // can print, then forever blocking
}

void main2() {
    std::async(std::launch::async, forever);
    std::cout << "printing" << std::endl; // forever blocking first, cannot print
}

void main3() {
    {std::future<void> p = std::async(std::launch::async, forever);}
    std::cout << "printing" << std::endl; // forever blocking first, cannot print
}

Take a look at cplusplus.com

看看cplusplus.com

Return value of std::async When launch::async is selected, the future returned is linked to the end of the thread created, even if its shared state is never accessed: in this case, its destructor synchronizes with the return of fn. Therefore, the return value shall not be disregarded for asynchronous behavior, even when fn returns void.

std :: async的返回值当选择了launch :: async时,返回的future将链接到创建的线程的末尾,即使从未访问过它的共享状态:在这种情况下,它的析构函数与fn的返回同步。因此,即使fn返回void,也不应忽略异步行为的返回值。

#1


16  

From just::thread documentation:

来自just :: thread文档:

If policy is std::launch::async then runs INVOKE(fff,xyz...) on its own thread. The returned std::future will become ready when this thread is complete, and will hold either the return value or exception thrown by the function invocation. The destructor of the last future object associated with the asynchronous state of the returned std::future shall block until the future is ready.

如果策略是std :: launch :: async,则在其自己的线程上运行INVOKE(fff,xyz ...)。当此线程完成时,返回的std :: future将变为就绪状态,并将保存函数调用抛出的返回值或异常。与返回的std :: future的异步状态关联的最后一个对象的析构函数将阻塞,直到将来准备就绪。

In

std::async(std::launch::async, foo, arg1, arg2);

The returned future is not assigned anywhere and its destructor blocks until foo finishes.

返回的未来不会分配到任何地方,它的析构函数会阻塞,直到foo结束。

#2


4  

I would like to add a link to an article by Herb Sutter on async and ~future in which he argues that futures should never block.

我想添加一个链接到Herb Sutter关于async和〜future的文章,他认为期货永远不应该阻止。

#3


0  

Why blocking?

为什么阻止?

  1. std::async(); returns std::future temporary object
  2. 的std ::异步();返回std :: future临时对象
  3. temporary object is destroyed immediately, calling desctructor.
  4. 临时对象立即被销毁,调用析构函数。
  5. std::future destructor is blocking. It is bad and troublesome.
  6. std :: future析构函数正在阻塞。这很糟糕而且很麻烦。

Why assigning is ok?

为什么分配是好的?

By assigning to a variable, the returned object is not destroyed immediately, but later, until end of scope of your calling code.

通过赋值给变量,返回的对象不会立即被销毁,而是稍后销毁,直到调用代码范围结束。

Code Example: main1 is ok. main2 and main3 are equivalently blocking the main thread.

代码示例:main1没问题。 main2和main3等效地阻塞主线程。

void forever() {
    while (true);
}

void main1() {
    std::future<void> p = std::async(std::launch::async, forever);
    std::cout << "printing" << std::endl; // can print, then forever blocking
}

void main2() {
    std::async(std::launch::async, forever);
    std::cout << "printing" << std::endl; // forever blocking first, cannot print
}

void main3() {
    {std::future<void> p = std::async(std::launch::async, forever);}
    std::cout << "printing" << std::endl; // forever blocking first, cannot print
}

Take a look at cplusplus.com

看看cplusplus.com

Return value of std::async When launch::async is selected, the future returned is linked to the end of the thread created, even if its shared state is never accessed: in this case, its destructor synchronizes with the return of fn. Therefore, the return value shall not be disregarded for asynchronous behavior, even when fn returns void.

std :: async的返回值当选择了launch :: async时,返回的future将链接到创建的线程的末尾,即使从未访问过它的共享状态:在这种情况下,它的析构函数与fn的返回同步。因此,即使fn返回void,也不应忽略异步行为的返回值。