面试题答案
一键面试引用计数 Rc
和原子引用计数 Arc
的主要区别
- 线程安全性
Rc
:Rc
是单线程引用计数,它不具备线程安全性。如果在多线程环境下使用Rc
,会导致未定义行为。因为Rc
内部的引用计数操作不是原子的,在多线程同时修改引用计数时可能会出现数据竞争。Arc
:Arc
是原子引用计数,具备线程安全性。Arc
内部的引用计数操作是原子的,这意味着多个线程可以安全地共享Arc
实例,对其引用计数的修改不会引发数据竞争。
- 性能
Rc
:由于Rc
不需要处理原子操作带来的开销,在单线程环境下,Rc
的性能会略高于Arc
。Arc
:由于原子操作会带来额外的开销,Arc
在性能上会比Rc
稍差一些,不过在多线程环境下,这种开销是保证线程安全所必需的。
使用 Arc
在简单多线程并发场景中共享数据的示例
use std::sync::{Arc, Mutex};
use std::thread;
fn main() {
// 创建一个 Arc 包裹的数据,这里用 Mutex 来保证数据的可变性
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
,Mutex
用于保证内部数据的线程安全可变访问。Arc
确保数据可以在多个线程间安全共享。 - 通过循环创建了10个线程,每个线程都克隆一份
Arc
实例。 - 在每个线程内部,通过获取
Mutex
的锁来修改内部的数据。 - 主线程等待所有线程完成后,打印最终的数据值。这样就实现了在多线程场景下安全地共享和修改数据。