问题
Consider I have lamba foo which just does some stuff and doesn't need to return anything.
When I do this:
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.
std::async(std::launch::async, foo, arg1, arg2);
What am I missing here?
回答1:
From just::thread documentation:
If policy is
std::launch::asyncthen runsINVOKE(fff,xyz...)on its own thread. The returnedstd::futurewill 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 returnedstd::futureshall block until the future is ready.
In
std::async(std::launch::async, foo, arg1, arg2);
The returned future is not assigned anywhere and its destructor blocks until foo finishes.
回答2:
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.
回答3:
Why blocking?
std::async();returnsstd::futuretemporary object- temporary object is destroyed immediately, calling desctructor.
std::futuredestructor is blocking. It is bad and troublesome.
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.
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
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.
来源:https://stackoverflow.com/questions/62312315/c-stdasync-is-being-called-synchronously-when-inside-a-switch-statement