面试题答案
一键面试在Rust中,要让多个线程共享一个字符串并进行读写操作,可以使用Arc
(原子引用计数)和Mutex
(互斥锁)或RwLock
(读写锁)来确保线程安全。以下是使用Arc
和Mutex
的示例:
use std::sync::{Arc, Mutex};
use std::thread;
fn main() {
// 创建一个Arc<Mutex<String>>
let shared_string = Arc::new(Mutex::new(String::from("Hello, ")));
let mut handles = vec![];
for _ in 0..3 {
let shared_string_clone = Arc::clone(&shared_string);
let handle = thread::spawn(move || {
// 锁定Mutex以获取字符串的可变引用
let mut s = shared_string_clone.lock().unwrap();
s.push_str("world! ");
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
// 主线程中打印最终结果
println!("{}", shared_string.lock().unwrap());
}
代码解释
Arc<Mutex<String>>
:Arc
(std::sync::Arc
)是原子引用计数指针,用于在多个线程间安全地共享数据。Mutex
(std::sync::Mutex
)是互斥锁,用于保护共享数据,确保同一时间只有一个线程可以访问数据。Mutex
提供了lock
方法,该方法返回一个Result
,成功时返回一个MutexGuard
智能指针,这个指针拥有对数据的独占访问权。
- 线程创建:
- 在循环中,通过
Arc::clone
复制Arc
指针,以便每个线程都能持有一份指向共享数据的引用。 - 每个线程通过
shared_string_clone.lock().unwrap()
获取Mutex
的锁,并获得字符串的可变引用,然后修改字符串。
- 在循环中,通过
- 等待线程结束:
- 使用
join
方法等待所有线程完成,确保所有修改都已完成。
- 使用
- 打印最终结果:
- 主线程中再次获取锁并打印最终的字符串。
如果读操作远多于写操作,也可以使用RwLock
(读写锁)来提高效率,示例如下:
use std::sync::{Arc, RwLock};
use std::thread;
fn main() {
let shared_string = Arc::new(RwLock::new(String::from("Hello, ")));
let mut handles = vec![];
for _ in 0..3 {
let shared_string_clone = Arc::clone(&shared_string);
let handle = thread::spawn(move || {
// 读取时使用read方法获取共享引用
let s = shared_string_clone.read().unwrap();
println!("Read: {}", s);
});
handles.push(handle);
}
let write_handle = thread::spawn(move || {
// 写入时使用write方法获取独占引用
let mut s = shared_string.write().unwrap();
s.push_str("world! ");
});
for handle in handles {
handle.join().unwrap();
}
write_handle.join().unwrap();
// 主线程中打印最终结果
println!("{}", shared_string.read().unwrap());
}
RwLock
解释
RwLock
允许同一时间有多个线程进行读操作,但只允许一个线程进行写操作。read
方法用于获取共享(只读)引用,write
方法用于获取独占(可写)引用。这样在读多写少的场景下可以提高并发性能。