In Rust, Arc
(Atomic Reference Counted) smart pointer enables shared ownership across threads, but it does not inherently eliminate the need for locks when mutable access to shared data is required. Here’s a breakdown:
Arc
Alone Suffices (No Locks Needed)Arc
is immutable (e.g., Arc<ReadOnlyData>
), no locks are needed. Multiple threads can safely read the data concurrently.use std::sync::Arc;
use std::thread;
let data = Arc::new(42); // Immutable data
let handles: Vec<_> = (0..10).map(|_| {
let data = Arc::clone(&data);
thread::spawn(move || {
println!("Data: {}", *data); // Safe concurrent reads
})
}).collect();
for handle in handles { handle.join().unwrap(); }
Arc
needs mutable access across threads, you must pair Arc
with a synchronization primitive like Mutex
or RwLock
(e.g., Arc<Mutex<T>>
).Mutex
):
use std::sync::{Arc, Mutex};
use std::thread;
let counter = Arc::new(Mutex::new(0));
let handles: Vec<_> = (0..10).map(|_| {
let counter = Arc::clone(&counter);
thread::spawn(move || {
let mut num = counter.lock().unwrap();
*num += 1; // Safe mutable access
})
}).collect();
for handle in handles { handle.join().unwrap(); }
println!("Result: {}", *counter.lock().unwrap());
std::sync::atomic
types (e.g., AtomicUsize
) for simple, lock-free operations.
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
use std::thread;
let counter = Arc::new(AtomicUsize::new(0));
let handles: Vec<_> = (0..10).map(|_| {
let counter = Arc::clone(&counter);
thread::spawn(move || {
counter.fetch_add(1, Ordering::SeqCst);
})
}).collect();
for handle in handles { handle.join().unwrap(); }
println!("Result: {}", counter.load(Ordering::SeqCst));
std::sync::mpsc
) to transfer ownership of data between threads instead of sharing it.
use std::sync::mpsc;
use std::thread;
let (tx, rx) = mpsc::channel();
for _ in 0..10 {
let tx = tx.clone();
thread::spawn(move || {
tx.send(1).unwrap();
});
}
drop(tx); // Close sender
println!("Result: {}", rx.iter().sum::<i32>());
thread_local!
for data that doesn’t need to be shared.Arc
manages ownership across threads, but not synchronization. To eliminate locks, avoid shared mutable state (use message passing, atomics, or immutable data). If you must mutate shared data, use Mutex
or RwLock
with Arc
.
Some contents are generated by Deepseek.