面试题答案
一键面试- 措施阐述
- 使用互斥锁(Mutex):在访问
UnsafeCell
内部数据时,通过互斥锁来确保同一时间只有一个线程可以访问。互斥锁会阻止其他线程进入临界区,从而避免数据竞争。 - 使用原子操作:对于简单的数据类型,如整数等,可以使用原子操作。原子操作在硬件层面保证了操作的原子性,即不可分割性,不会被其他线程打断,避免数据竞争。
- 使用互斥锁(Mutex):在访问
- 代码示例(以Rust语言为例)
use std::cell::UnsafeCell;
use std::sync::{Arc, Mutex};
use std::thread;
fn main() {
let shared_data = Arc::new(Mutex::new(UnsafeCell::new(0)));
let mut handles = vec![];
for _ in 0..10 {
let data = shared_data.clone();
let handle = thread::spawn(move || {
let mut data_ref = unsafe { &mut *data.lock().unwrap().get() };
*data_ref += 1;
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
let result = unsafe { *shared_data.lock().unwrap().get() };
println!("Final result: {}", result);
}
在上述代码中:
Arc
用于在多个线程间共享数据,Mutex
用于保证同一时间只有一个线程能访问UnsafeCell
。- 通过
lock
方法获取锁,进入临界区,访问UnsafeCell
内部数据并修改。
- 避免数据竞争
- 使用同步原语:如上述代码使用
Mutex
,它通过加锁和解锁机制,使得只有持有锁的线程能访问共享数据,其他线程等待锁的释放,从而避免多个线程同时修改共享数据导致的数据竞争。 - 遵循内存模型规则:在多线程编程中,要遵循所在编程语言的内存模型规则。例如在Rust中,通过所有权系统和类型系统来辅助避免数据竞争。在使用
UnsafeCell
时,通过unsafe
块来明确告知编译器程序员知道自己在做可能不安全的操作,同时结合同步原语确保操作的安全性。
- 使用同步原语:如上述代码使用