What is the difference between the two statements below in terms of execution?
async([]() { ... });
thread([]() { ... }).detach();
thread::detachSeparates the thread of execution from the thread object, allowing execution to continue independently. Any allocated resources will be freed once the thread exits.
Thus, you should always either join or detach a thread before the flows of execution reaches the destructor. When a program terminates (ie, main returns) the remaining detached threads executing in the background are not waited upon; instead their execution is suspended and their thread-local objects destructed.
5.6 [ISO/IEC 9899:2011], states that a thread shall not be joined once it was previously joined or detached. Similarly, subclause 7.26.
As the name indicates, C++ async is a function template fn, which takes functions or function objects as arguments (basically called callbacks) and runs them asynchronously. It returns the std:: the future object which is used to keep the result of the above function. The result is stored in the shared state.
std::async ([]() { ... }); // (1)
std::thread ([]() { ... }).detach (); // (2)
Most often when std::async
is being discussed the first thing noted is that it's broken, the name implies something which doesn't hold when the returned value isn't honored (assigned to a variable to be destructed at the end of the current scope).
In this case the brokenness of std::async
is exactly what is going to result in a huge difference between (1)
and (2)
; one will block, the other won't.
Why does std::async
block in this context?
The return-value of std::async
is a std::future
which has a blocking destructor that must execute before the code continues.
In an example as the below g
won't execute until f
has finished, simply because the unused return value of (3)
can't be destroyed until all work is done in the relevant statement.
std::async (f); // (3)
std::async (g); // (4)
What is the purpose of std::thread (...).detach ()
?
When detaching from a std::thread
we are simply saying; "I don't care about this thread handle anymore, please just execute the damn thing."
To continue with an example similar to the previous one (about std::async
) the difference is notably clear; both f
and g
will execute simultaneously.
std::thread (f).detach ();
std::thread (g).detach ();
I know a good answer was given to your question but if we were to change your question a little something interesting would occur.
Imagine you kept the future returned by the async
and didn't detach the thread but instead made a variable for it like this,
Asynchronous code
auto fut=std::async([]() { ... });
std::thread th([]() { ... });
Now you have the setup to what makes these 2 constructs different.
th.join()//you're here until the thread function returns
fut.wait_for(std::chrono::seconds(1)); //wait for 1 sec then continue.
A thread
is an all or nothing thing when joining it where as an async
can be checked and you can go do other stuff.
wait_for
actually returns a status so you can do things like this.
int numOfDots = 0;
//While not ready after waiting 1 sec do some stuff and then check again
while(fut.wait_for(std::chrono::seconds(1)) != std::future_status::ready)
{
(numOfDots++)%=20;
//Print status to the user you're still working on it.
std::cout << "Working on it" <<std::string(numOfDots,'.')<<"\r"<<std::flush();
}
std::cout << "Thanks for waiting!\nHere's your answer: " << fut.get() <<std::endl();
async
returns a future
object, detach
does not. All detach
does is allow the execution to continue independently. In order to achieve a similar effect as async
, you must use join
. For example:
{
std::async(std::launch::async, []{ f(); });
std::async(std::launch::async, []{ g(); }); // does not run until f() completes
}
{
thread1.join();
thread2.join();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With