Concurrency and parallelism in Dart
Let's get back to tech in this post starting with some background concepts.
Concepts
From a programming language perspective, Concurrency is how the language allows describing different parts of a computation (or program) so that they can be executed in different order. Check Wikipedia for a more formal definition.
Parallelism is having multiple executions of some computation one time.
Though they sound similar, both concepts are orthogonal. For parallelism you need to have the program run (and use) multi-core or multi-threaded CPU. It is possible to have a concurrent program that is not parallel since it runs in a single thread only. Most UI frameworks follow a single threaded model but allow for concurrent programming with event loops, promises/futures etc. Watch
(https://talks.golang.org/2012/waza.slide) for a better understanding of the topic.
Dart
Dart is a modern (only 10 years old) client-optimized language. The syntax is very java-esque but runs on multiple platforms and has a features like null safety, dynamics and a mature library. The killer application for dart is the flutter UI framework. The dart approach to concurrency and parallelism has some novel ideas that I'll provide some additional information on.
Concurrency based on async-await
Dart uses the async-await pattern for concurrent programming. As a quick example
Future<BigThing> createThing() async {
var aThing = await getAThing();
var otherThing = await getOtherThing();
return BigThing(aThing, otherThing);
}
Here createThing returns a Future which holds the result (or failure) from the delayed computation. Future is also called a Promise in other languages. It is possible to chain Futures like future.then(value => handleValue(value)) and so on but code quickly becomes unwieldy and unreadable. Instead using await on another Future returning method is equivalent to chaining but much more readable. This blog from C# explains the state machine created behind the scenes by the compiler in that language and I expect a similar model in dart, though I've not researched enough.
As the introduction hinted though, this code does not run in parallel though. Each future is a point where the program can then switch to running a different computation allowing for switching on a single thread. In fact if you don't use isolates (below) then there are no multithreading pitfalls to worry about - no deadlocks, no memory corruption. Programs and reasoning about them become much simpler.
Parallelism based on isolates
The dart virtual machine runs code in isolates. Each isolate has its own private memory and a single thread running an event loop.
Since only one-thread is working on private state (i.e. memory) programs are thread safe. Within an isolate the event loop handles all the events on the thread. Events can be user created like clicking on a button or system based like responses from some IO event. If you were await -ing on a response from a web request, when the payload is received the Future handling code can then be executed on the event loop.
When parallelism is required, it is possible to create (spawn) multiple Isolates. Isolates can communicate using messages, but importantly the memory is not shared. In the real world, the main UI loop is a single isolate and additional complex processing is in different isolates.
Meta
Dart is clearly inspired by the Javascript family of languages since they removed explicit threading.
The isolate model feels like a heavy-weight actor model inspired by Erlang
References
Async state machines in c# - https://devblogs.microsoft.com/premier-developer/dissecting-the-async-methods-in-c/
https://medium.com/dartlang/dart-asynchronous-programming-isolates-and-event-loops-bffc3e296a6a
and