use std::sync::{Mutex, Arc};
use std::thread;
fn main() {
// 创建一个被互斥锁保护的数据
let data = Arc::new(Mutex::new(0));
let mut handles = vec![];
for _ in 0..10 {
let data_clone = data.clone();
// 每个线程尝试获取锁并修改数据
let handle = thread::spawn(move || {
let mut num = data_clone.lock().unwrap();
*num += 1;
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
// 主线程获取锁并打印最终的数据
let final_result = data.lock().unwrap();
println!("Final result: {}", *final_result);
}
Rust通过所有权系统和类型系统确保线程安全的方式
- 所有权系统:
- 在Rust中,每个值都有一个唯一的所有者。当
Mutex<T>
创建时,T
类型的数据的所有权被转移到Mutex
内部。在上述代码中,Mutex
拥有i32
类型数据的所有权。
- 当一个线程尝试通过
lock()
方法获取锁时,它会获取到一个MutexGuard
类型的对象,这是一个智能指针。这个MutexGuard
对象在作用域结束时会自动释放锁,从而确保锁的正确管理。例如在let mut num = data_clone.lock().unwrap();
这行代码中,num
是MutexGuard<i32>
类型,在其离开作用域时(例如线程函数结束),锁会被自动释放。
- 类型系统:
Mutex<T>
是一个泛型类型,它确保只有实现了Send
和Sync
trait的类型T
才能被Mutex
保护。Send
trait表明类型的值可以安全地在线程间传递,Sync
trait表明类型的值可以安全地被多个线程共享。i32
类型实现了Send
和Sync
,所以可以被Mutex
保护。
- 类型系统还通过
MutexGuard
类型来确保只有获取到锁才能访问被保护的数据。由于MutexGuard
实现了Deref
和DerefMut
trait,所以可以像访问普通值一样访问被保护的数据,但只有在持有锁的情况下才能修改,这就保证了多线程环境下数据访问的安全性。