Fearless concurrency is the term used by the Rust community to refer to the features of the language that make concurrent programming faster and more secure.
Initially, the Rust team thought that ensuring memory safety and preventing concurrency problems were two separate challenges to be solved with different methods.
Over time, they discovered that the ownership and the type systems are a powerful set of tools that help manage memory safety and concurrency problems!
Concurrency is about multiple tasks which start, run, and complete in overlapping time periods, in no specific order.
An example is how your operating system executes many programs without waiting for others to finish.
Parallelism is about multiple tasks or subtasks of the same task that literally run at the same time on a hardware with multiple computing resources like multi-core processor.
An example is how your GPU calculates the color of each pixel at the same time.
While the concepts are similar, they are not the same thing.
Let us consider again the operating system example: normally the programs run at the same time together, parallely distributed on each core of the CPU.
However, some Operating Systems running on very cheap CPUs with only one thread execute all programs together but not at the same time, executing just a piece of each program at a time.
Splitting the functionality of your program into multiple threads can improve performance, but can also cause problems:
use std::thread;
use std::time::Duration;
fn main() {
thread::spawn(|| {
for i in 1..10 {
println!("hi number {} from the spawned thread!", i);
thread::sleep(Duration::from_millis(1));
}
});
for i in 1..5 {
println!("hi number {} from the main thread!", i);
thread::sleep(Duration::from_millis(1));
}
}
Output:
hi number 1 from the main thread!
hi number 1 from the spawned thread!
hi number 2 from the main thread!
hi number 2 from the spawned thread!
hi number 3 from the main thread!
hi number 3 from the spawned thread!
hi number 4 from the main thread!
hi number 4 from the spawned thread!
Some common types for concurrency are:
Arc<Mutex<T>>
: for sharing memory (try to avoid them, they are very slow)You can also create your own types, but they need to implement the Sync
and Send
traits.
Important note: implementing these traits is unsafe.
async/await
Creating threads is expensive in terms of performance. If you find yourself having a lot of tasks to complete, you may consider using async/await
.
In asynchronous Rust, each function that can do work is manually executed by a runtime executor.
async/await
, as a concept, is present in many languages, but each language implements it slightly differently.
async/await
async/await
is a purely concurrent concept, as such it can be useful for multithreading on servers, or for single threaded embedded chips.
There is no async
runtime in the standard library, you have to use an external library implementation or implement one yourself (try to avoid this as it's very hard).
The most popular one for multithreading is tokio.