- 使用
Mutex
实现线程安全的数据访问
Mutex
(互斥锁)是Rust中用于保护共享数据的常用工具。它通过在同一时间只允许一个线程访问数据来确保数据一致性。
- 示例代码:
use std::sync::{Arc, Mutex};
use std::thread;
fn main() {
let shared_data = Arc::new(Mutex::new(0));
let mut handles = vec![];
for _ in 0..10 {
let data = Arc::clone(&shared_data);
let handle = thread::spawn(move || {
let mut num = data.lock().unwrap();
*num += 1;
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
println!("Final value: {}", *shared_data.lock().unwrap());
}
- 在这段代码中,
Arc<Mutex<i32>>
用于在多个线程间共享一个i32
类型的数据。Mutex
确保在任何时刻只有一个线程可以获取锁并修改数据,Arc
用于在多个线程间共享这个Mutex
实例。
- 使用原子类型(
Atomic<T>
)
- 原子类型提供了一种无锁的方式来进行简单的数据操作,适用于一些不需要复杂同步逻辑的场景,例如简单的计数器。
- 示例代码:
use std::sync::atomic::{AtomicUsize, Ordering};
use std::thread;
fn main() {
let shared_counter = AtomicUsize::new(0);
let mut handles = vec![];
for _ in 0..10 {
let counter = shared_counter.clone();
let handle = thread::spawn(move || {
counter.fetch_add(1, Ordering::SeqCst);
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
println!("Final counter value: {}", shared_counter.load(Ordering::SeqCst));
}
- 在这个例子中,
AtomicUsize
类型的shared_counter
可以在多个线程间安全地进行fetch_add
操作,Ordering::SeqCst
指定了内存顺序,以确保操作的一致性。这种方式不需要像Mutex
那样获取和释放锁,对于简单的计数器操作性能更高。
- 结合
Mutex
和Condvar
处理复杂同步场景
Condvar
(条件变量)用于线程间的同步通信,通常与Mutex
一起使用。
- 示例代码:
use std::sync::{Arc, Condvar, Mutex};
use std::thread;
use std::time::Duration;
fn main() {
let pair = Arc::new((Mutex::new(false), Condvar::new()));
let pair2 = Arc::clone(&pair);
let handle = thread::spawn(move || {
let (lock, cvar) = &*pair2;
let mut started = lock.lock().unwrap();
*started = true;
drop(started);
cvar.notify_one();
});
let (lock, cvar) = &*pair;
let started = lock.lock().unwrap();
let started = cvar.wait_timeout(started, Duration::from_secs(2)).unwrap().0;
if started {
println!("The thread has started.");
} else {
println!("Timeout.");
}
handle.join().unwrap();
}
- 在这个代码中,主线程通过
Condvar
等待另一个线程发出的通知。Mutex
用于保护共享的布尔变量started
,确保线程安全地读写这个变量。当另一个线程修改了started
为true
后,通过Condvar
通知主线程,主线程收到通知后继续执行后续逻辑。