RUST
How to develop multi-threaded code
Mihalis Tsoukalos explains all you need to know about Rust and concurrency so you can assemble efficient multi-threaded tools.
OUR EXPERT
Mihalis Tsoukalos is a systems engineer and a technical writer. Find him online at @mactsouk.
QUICK TIP
Get the code for this tutorial from the Linux Format archive: www. linuxformat. com/archives ?issue=292. You can learn more about Rust at www. rust-lang.org.
This month’s instalment of our ongoing Rust series will cover concurrent programming. The difficulty with concurrency can be summed up as “Shared Mutable State is the root of all problems”. However, Rust takes a different approach towards concurrency. Instead of dealing with the mutable part, Rust deals with the shared part. Put simply, the Rust compiler will let you know about any errors in the “shared” part; therefore, if your Rust code compiles you have no such errors. As a result, it’s okay to have shared memory among threads in Rust.
So, it’s in concurrent programming that you might appreciate all the Rust rules regarding borrowing, ownership and mutability. To get us going we’ll present a simple concurrent Rust program that’s far from perfect.
Basic concurrency
Rust starts a new thread using the thread::spawn() function that’s part of the std::thread module. The core code of simple.rsis the following:
Two things are happening here. First, there’s a for loop used for calling thread::spawn() five times and therefore creating five threads. Second, there’s a call to thread::sleep() for delaying the termination of the thread. Threads usually don’t just print messages, but perform actual work that takes time. Let’s now run simple.rs, which generates the following output:
Start.
End.
First, bear in mind that there are two println!() statements before and after the for loop, which is the reason for the two lines of output. But where are the messages from the five threads? It looks like simple.rsdoesn’t behave as expected. The messages from the threads aren’t printed on screen, mainly because the main() function (in reality the thread used for executing the main() function) doesn’t wait for the five threads to finish – we can add an additional thread::sleep() call after the for loop for the main() thread to wait, but we can’t depend on such arbitrary parameters because we still don’t know how long it’s going to take the threads to finish and whether the sleep duration of the main() thread is going to give enough time to them.
The error message in
erroneous.rs and a hint about the solution produced by the Rust compiler when trying to compile it.
So, in our case, the main() function ends first, which means the entire program ends without giving the threads enough time to do their jobs. Additionally, the for loop in simple.rsignores the value of the loop parameter. But what happens if we want to print the value of the loop parameter? Read on!