Rust
Arc<T>
Learn thread-safe shared ownership with Arc<T>.
Arc<T>
Arc<T> (atomically reference counted) is the thread-safe version of Rc. It updates the counter with atomic operations; it's slightly slower but can be shared across threads:
use std::sync::Arc;
use std::thread;
let veri = Arc::new(vec![1, 2, 3]);
let v = Arc::clone(&veri);
let h = thread::spawn(move || v.iter().sum::<i32>());
println!("{}", h.join().unwrap()); // 6
Each thread takes its own Arc copy with move. The data is read-only; changing it needs Arc<Mutex<T>>.
Collecting results in order
The output order of threads is undetermined. Getting results with join both waits for them to finish and collects them in order:
let tutucular: Vec<_> = (1..=3)
.map(|k| {
let v = Arc::clone(&veri);
thread::spawn(move || v.iter().sum::<i32>() * k)
})
.collect();
let sonuc: Vec<i32> = tutucular.into_iter().map(|h| h.join().unwrap()).collect();
Once all threads finish, their copies are dropped too and the counter is back to 1.
Exercise Parallel sum
Share Arc::new(vec![1, 2, 3]). Start three threads for k = 1..=3, each computing sum * k, and collect the results in order with join. Print the result vector and the final Arc::strong_count value separated by a space.
Show example solution
use std::sync::Arc;
use std::thread;
fn main() {
let veri = Arc::new(vec![1, 2, 3]);
let tutucular: Vec<_> = (1..=3)
.map(|k| {
let v = Arc::clone(&veri);
thread::spawn(move || v.iter().sum::<i32>() * k)
})
.collect();
let sonuc: Vec<i32> = tutucular.into_iter().map(|h| h.join().unwrap()).collect();
println!("{:?} {}", sonuc, Arc::strong_count(&veri));
}
Test yourself
-
What happens if an <code>Rc</code> is used inside <code>thread::spawn(move || ..)</code>?
- It works but is slow
- Runtime panic
- No problem
- Compile error: Rc can't be sent safely between threads (not Send)
Show answer
Compile error: Rc can't be sent safely between threads (not Send) — The compiler prevents data races at compile time with the Send/Sync traits.
-
Thread-safe sharing
use std::sync::Arc;
let veri = ____::new(vec![1, 2, 3]);
Show answer
use std::sync::Arc;
let veri = Arc::new(vec![1, 2, 3]);
-
Type and property
- Rc<T>
- Single thread, sharing
- Arc<T>
- Multiple threads, sharing
- Box<T>
- Single owner
- Arc<Mutex<T>>
- Shared mutation
Next lesson: Box and recursion