Send and Sync
- Send: the type can be moved between threads.
- Sync: a type can be shared between threads (logically equivalent to
&T
being Send)
By default, most types are Send and Sync. If a type is moved to another
thread, it is fine because it owns its data and therefore nothing else can
touch that data or cause thread safety issues. If a shared reference is moved to
another thread, that is fine because the mere existence of a
shared reference means the data can no longer mutate, so there’s nothing
needing synchronization between threads. If an exclusive reference is moved, again
it is fine because that exclusive reference is the only thing
allowed to look at or modify the underlying data, so there is no need to
synchronize anything. The only types that are not both Send and Sync are
types that cheat the aliasing and ownership rules like UnsafeCell<T>
and
Rc<T>
.
Luckily, Java actually allows for this to be enforced. Arena.ofConfined()
gives us
a thread-local memory arena, and if code tries to use a MemorySegment
allocated from this arena in another thread it will throw an exception. This is
an absolute life saver, as it allows for the use of RefCell<T>
, which is neither
Send nor Sync, and which is useful for fixing many of the incongruities
between Java and Rust’s memory models.
Example of Thread Safety and Send and Sync
use std::sync::{Arc, Mutex};
use std::thread;
fn main() {
let calculator = Arc::new(Mutex::new(PostfixCalculator::new()));
let calculator_clone = Arc::clone(&calculator);
let handle = thread::spawn(move || {
let mut calc = calculator_clone.lock().unwrap();
let tokens: Vec<&str> = "3 4 +".split_whitespace().collect();
calc.evaluate(tokens)
});
match handle.join().unwrap() {
Ok(result) => println!("Result from thread: {}", result),
Err(e) => println!("Error from thread: {}", e),
}
}
Thread Safety: The Arc and Mutex wrapping of PostfixCalculator
ensures that
it can be safely shared and mutated across threads. Arc allows for shared
ownership across threads, while Mutex provides mutual exclusion,
preventing data races.
To learn more about Send and Sync traits, it is recommended to read these official Rust resources: The Rust Programming Language chapter 16.4, and The Rustonomicon chapter 8.2.