MST

星途 面试题库

面试题:Rust中使用Cell类型实现线程安全数据结构

假设你要设计一个多线程环境下的计数器数据结构,要求能够高效地进行原子操作。请使用Rust语言,结合Cell类型(或合适的替代类型),实现这个计数器数据结构,并展示如何在多线程环境中安全地使用它。同时,分析你的实现中可能存在的性能瓶颈。
47.3万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试
use std::cell::Cell;
use std::sync::{Arc, Mutex};
use std::thread;

// 使用Cell和Mutex实现多线程安全的计数器
struct ThreadSafeCounter {
    inner: Arc<Mutex<Cell<u64>>>,
}

impl ThreadSafeCounter {
    fn new() -> Self {
        ThreadSafeCounter {
            inner: Arc::new(Mutex::new(Cell::new(0))),
        }
    }

    fn increment(&self) {
        let mut guard = self.inner.lock().unwrap();
        let value = guard.get();
        guard.set(value + 1);
    }

    fn get(&self) -> u64 {
        let guard = self.inner.lock().unwrap();
        guard.get()
    }
}

fn main() {
    let counter = ThreadSafeCounter::new();
    let handles: Vec<_> = (0..10)
      .map(|_| {
            let counter_clone = counter.clone();
            thread::spawn(move || {
                for _ in 0..1000 {
                    counter_clone.increment();
                }
            })
        })
      .collect();

    for handle in handles {
        handle.join().unwrap();
    }

    println!("Final counter value: {}", counter.get());
}

性能瓶颈分析:

  1. Mutex 锁开销:每次对计数器的操作(incrementget)都需要获取和释放 Mutex 锁。锁的获取和释放操作会带来一定的性能开销,尤其是在高并发场景下,频繁的锁竞争会导致线程上下文切换,降低系统整体性能。
  2. 缓存一致性问题:由于 Mutex 保护的数据在多个线程间共享,现代多核 CPU 的缓存一致性协议(如 MESI)需要在不同核心的缓存间同步数据。当一个线程修改了计数器的值,其他核心缓存中的数据就会失效,需要从主内存重新读取,这也会带来额外的性能损耗。