- 同步机制选择:
Mutex
(互斥锁):适用于需要独占访问静态变量的场景,当多个线程中可能有读有写操作时,使用Mutex
能保证同一时间只有一个线程可以访问和修改静态变量,从而避免竞争条件。
RwLock
(读写锁):当读操作远多于写操作时,RwLock
更合适。它允许多个线程同时进行读操作,但写操作必须独占。读操作不会修改数据,所以允许多个线程同时读可以提高效率,而写操作需要保证数据一致性,所以必须独占。
- 与静态值存储的关系:
- Rust中的静态变量默认是不可变的。如果要让多个线程可以修改静态变量,需要将其声明为
mut
可变的,并且使用同步机制来保护其并发访问。
- 静态变量的生命周期是整个程序的运行期,这与同步机制的作用相契合,因为同步机制也是为了在整个程序运行过程中保证对共享资源(这里的静态变量)的安全访问。
- 代码示例(使用
Mutex
):
use std::sync::{Mutex, Arc};
use std::thread;
static mut SHARED_DATA: i32 = 0;
fn main() {
let shared_data = Arc::new(Mutex::new(SHARED_DATA));
let mut handles = vec![];
for _ in 0..10 {
let data = Arc::clone(&shared_data);
let handle = thread::spawn(move || {
let mut guard = data.lock().unwrap();
*guard += 1;
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
let final_value = shared_data.lock().unwrap();
println!("Final value: {}", *final_value);
}
- 在这个示例中,首先将静态变量
SHARED_DATA
用Mutex
包裹在Arc
中,Arc
用于在多个线程间共享所有权。每个线程通过获取Mutex
的锁(lock
方法)来访问和修改静态变量。获取锁可能会失败(例如其他线程正在持有锁),所以使用unwrap
来简单处理错误。最后在主线程中获取最终的值并打印。
- 代码示例(使用
RwLock
):
use std::sync::{RwLock, Arc};
use std::thread;
static mut SHARED_DATA: i32 = 0;
fn main() {
let shared_data = Arc::new(RwLock::new(SHARED_DATA));
let mut handles = vec![];
for _ in 0..5 {
let data = Arc::clone(&shared_data);
let handle = thread::spawn(move || {
let guard = data.read().unwrap();
println!("Read value: {}", *guard);
});
handles.push(handle);
}
for _ in 0..3 {
let data = Arc::clone(&shared_data);
let handle = thread::spawn(move || {
let mut guard = data.write().unwrap();
*guard += 1;
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
let final_value = shared_data.read().unwrap();
println!("Final value: {}", *final_value);
}
- 此示例中,使用
RwLock
来保护静态变量SHARED_DATA
。对于读操作,使用read
方法获取读锁,允许多个线程同时读。对于写操作,使用write
方法获取写锁,保证同一时间只有一个线程可以写。同样使用unwrap
简单处理获取锁失败的情况。最后在主线程中读取最终的值并打印。通过这种方式,能有效处理竞争条件和数据一致性问题。