面试题答案
一键面试AtomicUsize
保证原子性的原理:AtomicUsize
是Rust标准库中提供的原子类型,它基于底层硬件提供的原子操作指令(如x86架构上的lock
前缀指令等)。这些原子操作指令确保对AtomicUsize
类型变量的读、写和修改操作是不可分割的,在多线程环境下不会出现数据竞争。例如,当一个线程对AtomicUsize
进行自增操作时,硬件层面会保证这个操作在执行过程中不会被其他线程打断,从而保证了ID分配的原子性。
- 示例代码:
use std::sync::{Arc, atomic::{AtomicUsize, Ordering}};
use std::thread;
fn main() {
let counter = Arc::new(AtomicUsize::new(0));
let mut handles = vec![];
for _ in 0..10 {
let counter_clone = Arc::clone(&counter);
let handle = thread::spawn(move || {
let id = counter_clone.fetch_add(1, Ordering::SeqCst);
println!("Thread got ID: {}", id);
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
}
在上述代码中:
- 首先创建了一个
AtomicUsize
类型的counter
,初始值为0。 - 然后通过
thread::spawn
创建10个线程,在每个线程中使用fetch_add
方法对counter
进行自增操作并获取当前值作为线程的唯一ID。fetch_add
方法会以原子方式增加AtomicUsize
的值,并返回增加前的值。 Ordering::SeqCst
是一种内存序,它提供了最强的同步保证,确保所有线程都以相同的顺序观察到对原子变量的修改。- 最后通过
join
等待所有线程完成。