面试题答案
一键面试线程安全条件
- 不可变数据:如果
MyType
中的所有字段都是不可变的,那么它天然就是线程安全的。因为不可变数据在多个线程中读取不会引发数据竞争。 - 实现
Sync
trait:如果MyType
包含可变数据,那么它需要实现Sync
trait。Sync
trait 标记类型可以安全地在多个线程间共享。类型的所有字段也都必须实现Sync
,Rust 会自动为满足条件的类型实现Sync
。对于包含内部可变性(如Cell
或RefCell
)的类型,需要特别注意,因为这些类型默认不实现Sync
。通常需要使用线程安全的内部可变性类型,如Mutex
或RwLock
来包装可变数据。
代码示例
use std::sync::{Arc, Mutex};
// 定义一个自定义类型
struct MyType {
data: i32,
}
// 为MyType实现Sync trait,由于i32实现了Sync,这里会自动推导实现
unsafe impl Sync for MyType {}
fn main() {
// 使用Arc和Mutex来在多个线程间安全地共享MyType实例
let my_type = Arc::new(Mutex::new(MyType { data: 0 }));
let handles = (0..10).map(|_| {
let my_type_clone = my_type.clone();
std::thread::spawn(move || {
let mut my_type = my_type_clone.lock().unwrap();
my_type.data += 1;
})
}).collect::<Vec<_>>();
for handle in handles {
handle.join().unwrap();
}
let my_type = my_type.lock().unwrap();
println!("Final value: {}", my_type.data);
}
在上述示例中,MyType
结构体包含一个 i32
类型的字段 data
。由于 i32
实现了 Sync
,MyType
也实现了 Sync
(虽然这里是自动推导的,但为了展示显式实现也可以加上 unsafe impl Sync for MyType {}
)。然后通过 Arc<Mutex<MyType>>
来在多个线程间安全地共享和修改 MyType
实例。Arc
用于线程间共享引用计数,Mutex
用于提供互斥访问可变数据的能力。