I'm learning about the uses of async/await in Scala. I have read this in https://github.com/scala/async
Theoretically this code is asynchronous (non-blocking), but it's not parallelized:
def slowCalcFuture: Future[Int] = ... def combined: Future[Int] = async { await(slowCalcFuture) + await(slowCalcFuture) } val x: Int = Await.result(combined, 10.seconds)
whereas this other one is parallelized:
def combined: Future[Int] = async { val future1 = slowCalcFuture val future2 = slowCalcFuture await(future1) + await(future2) }
The only difference between them is the use of intermediate variables. How can this affect the parallelization?
This is a proposal to add constructs that simplify asynchronous and concurrent programming in Scala. The main constructs, async and await, are inspired by similar constructs introduced in C# 5.0.
Scala-async is a library for asynchronous programming. It provides a simple API to handle asynchronous method calls using the imperative way, which in some cases is more convenient. It was first added in C# and F# and then ported to other languages like Scala, Python, Javascript etc.
Line 1 defines an asynchronous method: it returns a Future. Line 2 begins an async block. During compilation, the contents of this block will be analyzed to identify the await calls, and transformed into non-blocking code. Control flow will immediately pass to line 5, as the computation in the async block is not executed on the caller's thread.
Async is an object with only two methods namely ‘async ()’ and ‘await ()’. The main use case of Async object is to conveniently and efficiently code in asynchronous way. It can be considered as another alternative of low-level callbacks or high order functions like map and flat-map.
Since it's similar to async & await
in C#, maybe I can provide some insight. In C#, it's a general rule that Task
that can be awaited should be returned 'hot', i.e. already running. I assume it's the same in Scala, where the Future
returned from the function does not have to be explicitly started, but is just 'running' after being called. If it's not the case, then the following is pure (and probably not true) speculation.
Let's analyze the first case:
async { await(slowCalcFuture) + await(slowCalcFuture) }
We get to that block and hit the first await:
async { await(slowCalcFuture) + await(slowCalcFuture) ^^^^^ }
Ok, so we're asynchronously waiting for that calculation to finish. When it's finished, we 'move on' with analyzing the block:
async { await(slowCalcFuture) + await(slowCalcFuture) ^^^^^ }
Second await, so we're asynchronously waiting for second calculation to finish. After that's done, we can calculate the final result by adding two integers.
As you can see, we're moving step-by-step through awaits, awaiting Future
s as they come one by one.
Let's take a look at the second example:
async { val future1 = slowCalcFuture val future2 = slowCalcFuture await(future1) + await(future2) }
OK, so here's what (probably) happens:
async { val future1 = slowCalcFuture // >> first future is started, but not awaited val future2 = slowCalcFuture // >> second future is started, but not awaited await(future1) + await(future2) ^^^^^ }
Then we're awaiting the first Future
, but both of the futures are currently running. When the first one returns, the second might have already completed (so we will have the result available at once) or we might have to wait for a little bit longer.
Now it's clear that second example runs two calculations in parallel, then waits for both of them to finish. When both are ready, it returns. First example runs the calculations in a non-blocking way, but sequentially.
the answer by Patryk is correct if a little difficult to follow. the main thing to understand about async/await is that it's just another way of doing Future
's flatMap
. there's no concurrency magic behind the scenes. all the calls inside an async block are sequential, including await which doesn't actually block the executing thread but rather wraps the rest of the async block in a closure and passes it as a callback on completion of the Future
we're waiting on. so in the first piece of code the second calculation doesn't start until the first await has completed since no one started it prior to that.
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