MST
星途 面试题库

面试题:Rust向量容量规划在高并发场景下的考量

在一个高并发的Rust程序中,多个线程会同时向一个共享的向量`Vec<u64>`中添加元素,预计总元素数量在10000 - 20000之间波动。请阐述在这种场景下,如何合理规划向量的容量以避免频繁的内存重分配导致的性能瓶颈和数据竞争问题?详细说明你所采用的策略,涉及到的Rust特性(如原子操作、线程安全的数据结构等)以及对应的代码实现思路。
29.8万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试
  1. 容量规划策略
    • 由于预计总元素数量在10000 - 20000之间波动,可以预先分配一个相对较大的容量,比如20000,这样可以减少内存重分配的次数。在Rust中,Vec提供了with_capacity方法来预先分配容量。
  2. 避免数据竞争问题
    • 使用线程安全的数据结构
      • 可以使用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);
}

通过上述策略,可以有效避免频繁的内存重分配以及数据竞争问题,提升高并发场景下程序的性能。