面试题答案
一键面试- 容量规划策略:
- 由于预计总元素数量在10000 - 20000之间波动,可以预先分配一个相对较大的容量,比如20000,这样可以减少内存重分配的次数。在Rust中,
Vec
提供了with_capacity
方法来预先分配容量。
- 由于预计总元素数量在10000 - 20000之间波动,可以预先分配一个相对较大的容量,比如20000,这样可以减少内存重分配的次数。在Rust中,
- 避免数据竞争问题:
- 使用线程安全的数据结构:
- 可以使用
std::sync::Arc
(原子引用计数指针)和std::sync::Mutex
(互斥锁)来包装Vec<u64>
。Arc
用于在多个线程间共享数据,Mutex
用于保护共享数据的访问,确保同一时间只有一个线程可以修改Vec
。 - 示例代码如下:
- 可以使用
- 使用线程安全的数据结构:
use std::sync::{Arc, Mutex};
use std::thread;
fn main() {
let shared_vec = Arc::new(Mutex::new(Vec::with_capacity(20000)));
let mut handles = vec![];
for _ in 0..10 {
let shared_vec_clone = Arc::clone(&shared_vec);
let handle = thread::spawn(move || {
let mut vec = shared_vec_clone.lock().unwrap();
for i in 0..1000 {
vec.push(i as u64);
}
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
let final_vec = shared_vec.lock().unwrap();
println!("Final vector has {} elements", final_vec.len());
}
- 原子操作(可选):
- 如果只是单纯地统计添加元素的个数,可以使用
std::sync::atomic::AtomicU64
来进行原子操作,避免使用锁来统计元素个数带来的性能开销。例如:
- 如果只是单纯地统计添加元素的个数,可以使用
use std::sync::{Arc, Mutex};
use std::thread;
use std::sync::atomic::{AtomicU64, Ordering};
fn main() {
let shared_vec = Arc::new(Mutex::new(Vec::with_capacity(20000)));
let element_count = Arc::new(AtomicU64::new(0));
let mut handles = vec![];
for _ in 0..10 {
let shared_vec_clone = Arc::clone(&shared_vec);
let element_count_clone = Arc::clone(&element_count);
let handle = thread::spawn(move || {
let mut vec = shared_vec_clone.lock().unwrap();
for i in 0..1000 {
vec.push(i as u64);
element_count_clone.fetch_add(1, Ordering::SeqCst);
}
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
let final_count = element_count.load(Ordering::SeqCst);
println!("Total elements added: {}", final_count);
}
通过上述策略,可以有效避免频繁的内存重分配以及数据竞争问题,提升高并发场景下程序的性能。