1

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?

2 Answers2

7

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.

Lukas-T
  • 11,133
  • 3
  • 20
  • 30
  • But its not guaranteed to be run in parallel? It might run _asynchronously_ but for the purpose of concurrency that doesnt help necessarily? – Object object Feb 21 '20 at 11:01
  • @TheGoldKnight23 I'm not 100% sure on this. You can specify some flag to force the creation of a new thread, but by default the implementation will decide this. – Lukas-T Feb 21 '20 at 11:19
  • Which makes it less useful compared with std::thread for control over concurrency – Object object Feb 21 '20 at 11:35
  • Only when std::launch::async is set, a parallel processing is done. – SKCoder Feb 21 '20 at 12:26
  • Ok, might want to clarify the above answer to reflect that – Object object Feb 21 '20 at 12:30
  • @TheGoldKnight23 `std::async` is not intended to be a replacement for threading. I wouldn't it's not more or less usefull, it's just something different. – Lukas-T Feb 21 '20 at 12:33
  • 1
    @SKCoder `std::launch::async` and `std::launch::deferred` are both set by default, so the implementation decides what happens. But all of this can be found on the linked reference and in my opinion not of importance for the question at hand. – Lukas-T Feb 21 '20 at 12:35
2

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

Object object
  • 1,939
  • 10
  • 19