Creating threads

In Rust, things are similar to the C++ approach, where we have the std::thread module with the spawn() function. This function will receive a closure or a pointer to a function and execute it. It will return a handle to the thread, and we will be able to manage it from outside. Let's see how this works:

use std::thread;

fn main() {
println!("Before the thread!");

let handle = thread::spawn(|| {
println!("Inside the thread!");
});
println!("After thread spawn!");

handle.join().expect("the thread panicked");
println!("After everything!");
}

This will output something similar to this:

The Inside the thread! and After thread spawn! messages could be ordered in any way, in theory, even though in this simple example it is easy to see that spawning the thread will take more time than printing in the screen buffer.

Nevertheless, this example shows some valuable information on how to work with threads. First, when the Before the thread! message gets printed, there is only one thread in execution: the main thread, running the main() function.

Then, we spawn a new thread with the std::thread::spawn() function, and we pass a simple closure to it. This closure will just print the Inside the thread! message in the console. This happens at the same time as the printing of the After thread spawn! message. In fact, in some programming languages, you might see that the characters of both messages get mixed and the final message is just a lot of incomprehensible characters.

Rust avoids this by only accessing the standard output file descriptor with a Mutex. The println!() macro will lock stdout while it writes the message, and if a new message wants to be written, it will have to wait until the first write finishes.

This has both advantages and disadvantages. As a clear advantage, the printed messages are clearly readable, since one of the threads (the main thread or the second thread) will always arrive before the other. On the other hand, it means that while the second thread is waiting for the first one to finish printing on the screen, it will be blocked and won't be able to do any computation.

You will need to make sure that you take that into account, and don't print frequently from many threads while performing computations. In fact, since Rust is a thread-safe language, it will happen with any shared resource, so you will need to be careful to avoid overhead.

You might think that this is a bad approach for performance, since it will make things slower, but actually, it's the only possible approach if the integrity of the data needs to be preserved. In other languages, you will need to implement the solution yourself, or use existing solutions explicitly to avoid memory corruption.

Before the end of the example code, we can see that we call the join() method in the thread handle. This will make the current thread wait for the other one to finish. You might note that I added a call to the expect() method after it. This is because the join() method returns a Result because it might have panicked before finishing.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.29.22