user12363684
user12363684

Reputation:

Why std::async runs functions with a same thread

I was reading an article about concurrent programming with c++ (link). In this article, author shows a code that std::async runs two functions with the same thread. Also, when he used std::future with std::async, it acts differently again and runs all functions with independent threads. Why async behave like that and it has this uncontrolled manner? also, How can I develope a real concurrent program with this feature? is that possible at all or I should miss it?

Upvotes: 1

Views: 1502

Answers (2)

Lukas-T
Lukas-T

Reputation: 11340

I suggests to also read the reference, where it is better explained what happens, in the "Notes"-section

If the std::future obtained from std::async is not moved from or bound to a reference, the destructor of the std::future will block at the end of the full expression until the asynchronous operation completes [...]

Or in other words std::async returns a std::future. Once that returned object gets destroyed it will wait until the running operation it represents ends. So, if you discard the return value like

std::async(xyz);

The destructor of the returned value gets called immediately after returning and thus waits for the completion of xyz.

If you keep the returned value like

auto futureXyz = std::async(xyz);

it does run parallel. That's because the returned value gets moved to the variable futureXyz, so the local variable "owns" the parallel executing function.

I wouldn't call this "uncontrolled behaviour", it's just something you would not expect, but it's well defined.

Upvotes: 7

Object object
Object object

Reputation: 2054

From the cppreference docs on std::async:

...runs the function f asynchronously (potentially in a separate thread...) (bold is mine).

std::async does not guarantee spawning a separate thread to execute the instruction, if you need a separate thread for definite use std::thread. This will guarantee a separate thread is spawned and you can communicate with it using std::future, atomic variables, etc.

Example code:

std::mutex cout_lock;
auto thread = std::thread([]{
  std::lock_guard<mutex> lock(cout_lock);
  std::cout << "Hello world from thread!\n";
});

std::lock_guard<mutex> lock(cout_lock);
std::cout << "Hello world!\n";
thread.join();

Notice how my above code uses mutex's since cout is not inherently thread-safe

Upvotes: 2

Related Questions