面试题答案
一键面试针对 Vec
- 实现思路:
- 将
Vec
封装在一个可跨线程共享的数据结构中,确保对其的访问是线程安全的。 - 在线程间传递对这个共享数据结构的引用,并使用同步机制来控制对
Vec
的访问。
- 将
- 可能用到的同步原语:
Mutex
:使用std::sync::Mutex
来包裹Vec
。Mutex
提供了互斥锁的功能,同一时间只有一个线程可以获取锁并访问Vec
,从而避免数据竞争。例如:
use std::sync::{Mutex, Arc};
use std::thread;
fn main() {
let shared_vec = Arc::new(Mutex::new(vec![1, 2, 3]));
let mut handles = vec![];
for _ in 0..10 {
let shared_vec_clone = shared_vec.clone();
let handle = thread::spawn(move || {
let mut vec = shared_vec_clone.lock().unwrap();
vec.push(4);
println!("{:?}", vec);
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
}
RwLock
:如果读操作远多于写操作,可以考虑使用std::sync::RwLock
。它允许多个线程同时进行读操作,但只允许一个线程进行写操作。写操作会独占锁,阻止其他读写操作。例如:
use std::sync::{RwLock, Arc};
use std::thread;
fn main() {
let shared_vec = Arc::new(RwLock::new(vec![1, 2, 3]));
let mut handles = vec![];
for _ in 0..5 {
let shared_vec_clone = shared_vec.clone();
let handle = thread::spawn(move || {
let vec = shared_vec_clone.read().unwrap();
println!("{:?}", vec);
});
handles.push(handle);
}
for _ in 0..2 {
let shared_vec_clone = shared_vec.clone();
let handle = thread::spawn(move || {
let mut vec = shared_vec_clone.write().unwrap();
vec.push(4);
println!("{:?}", vec);
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
}
针对 LinkedList
- 实现思路:
- 与
Vec
类似,将LinkedList
封装在一个线程安全的数据结构中。由于LinkedList
的节点在内存中不连续,在多线程环境下访问时要特别注意节点的修改和删除操作,防止出现悬空指针等问题。
- 与
- 可能用到的同步原语:
Mutex
:同样可以使用std::sync::Mutex
包裹LinkedList
。通过获取锁来保证同一时间只有一个线程能访问和修改LinkedList
。例如:
use std::sync::{Mutex, Arc};
use std::collections::LinkedList;
use std::thread;
fn main() {
let shared_list = Arc::new(Mutex::new(LinkedList::from(vec![1, 2, 3])));
let mut handles = vec![];
for _ in 0..10 {
let shared_list_clone = shared_list.clone();
let handle = thread::spawn(move || {
let mut list = shared_list_clone.lock().unwrap();
list.push_back(4);
println!("{:?}", list);
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
}
RwLock
:当读多写少场景时,使用std::sync::RwLock
包裹LinkedList
,读操作可以并发执行,写操作则独占锁。例如:
use std::sync::{RwLock, Arc};
use std::collections::LinkedList;
use std::thread;
fn main() {
let shared_list = Arc::new(RwLock::new(LinkedList::from(vec![1, 2, 3])));
let mut handles = vec![];
for _ in 0..5 {
let shared_list_clone = shared_list.clone();
let handle = thread::spawn(move || {
let list = shared_list_clone.read().unwrap();
println!("{:?}", list);
});
handles.push(handle);
}
for _ in 0..2 {
let shared_list_clone = shared_list.clone();
let handle = thread::spawn(move || {
let mut list = shared_list_clone.write().unwrap();
list.push_back(4);
println!("{:?}", list);
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
}
此外,对于更复杂的场景,还可以考虑使用 Atomic
类型结合 Mutex
或 RwLock
来进一步优化性能和保证数据一致性。