面试题答案
一键面试- 线程安全措施:
- 共享数据保护:使用锁机制(如
Mutex
)来保护共享数据,防止多个线程同时访问和修改,从而避免数据竞争。 - 消息传递:使用通道(
channel
)在不同线程间安全地传递数据,而不是直接共享数据。这是Rust基于“所有权”和“借用”原则的并发编程的重要方式。
- 共享数据保护:使用锁机制(如
- 使用
Mutex
避免数据竞争示例:
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;
println!("Thread incremented data to: {}", *num);
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
println!("Final data value: {}", *shared_data.lock().unwrap());
}
在上述代码中:
Arc<Mutex<T>>
用于在多个线程间安全地共享数据T
。Arc
(原子引用计数)允许在多个线程间共享数据的所有权,Mutex
提供了互斥访问,确保同一时间只有一个线程可以访问数据。- 在每个线程中,通过
data.lock().unwrap()
获取锁,如果获取成功(unwrap
在这里假设获取锁不会失败),则可以安全地修改共享数据。 - 主线程等待所有子线程完成,最后打印出共享数据的最终值。
- 使用通道示例:
use std::sync::mpsc;
use std::thread;
fn main() {
let (tx, rx) = mpsc::channel();
let mut handles = vec![];
for _ in 0..10 {
let tx_clone = tx.clone();
let handle = thread::spawn(move || {
// 发送数据到通道
tx_clone.send(1).unwrap();
});
handles.push(handle);
}
let mut sum = 0;
for _ in 0..10 {
// 从通道接收数据
sum += rx.recv().unwrap();
}
for handle in handles {
handle.join().unwrap();
}
println!("Sum of received data: {}", sum);
}
在这个示例中:
mpsc::channel()
创建了一个多生产者单消费者通道。- 每个线程使用
tx.send()
将数据发送到通道,主线程使用rx.recv()
从通道接收数据。这种方式通过消息传递避免了共享数据带来的数据竞争问题。