Just like with memory, Rust is quite good at finding out potential concurrency problems during compilation.
Rust implements 1:1 threads, so when we create a thread in Rust, an actual thread is also created by the OS. There are crates that implement Mthreading.
Creating a New Thread
Threads run closures. If the
main() function finishes before threads finish
execution, they will be terminated anyway.
JoinHandle may be used to wait for a thread to finish its execution. Its is
The app will finish only when the thread is done.
Sometimes we might want one thread to pass ownership of some value to another
thread. We can do that with the
move keyword placed before the closure.
Threads can communicate via channels where a transmitter sends messages and receiver receives them.
send() method takes ownership of the value being sent and transfers
ownership to the receiving thread. d
Data can be guarded by a mutex, which allows access to that data to only one thread at a time.
To get access to data protected by a
Mutex, we have to call
lock() on it.
This is a blocking call, execution will continue as soon as either:
- lock is free
- other thread that had the lock panics
The lock is released as soon as
MutexGuard goes out of scope.
We can’t use
Rc<T> in multithreaded contexts. Instead, we can use
is thread safe (and has some performance overhead due to that).
We can use
Arc to share values between many threads. Example below shares a
There are a few traits that are important for concurrency.
Send marker trait indicates that ownership of values of the type
Send can be transferred between threads. Most types implement it
with some exceptions (like
Rc, which is not thread-safe). Any type that
Send-marked fields is automatically marked as
Send as well.
Sync marker trait indicates that it is safe for the type implementing
Sync to be referenced from multiple threads. Similar to
Send, types composed
entirely of types that are
Sync are also