MST

星途 面试题库

面试题:Rust并发编程中如何识别竞态条件

在Rust并发编程场景下,描述一下可能出现竞态条件的几种典型代码模式,例如在多线程访问共享资源时,从变量声明、线程启动及资源访问等角度说明,并且解释为什么这些模式容易引发竞态条件。
37.8万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试
  1. 共享可变变量未加同步机制
    • 代码模式
fn main() {
    let mut data = 0;
    std::thread::spawn(|| {
        data += 1;
    }).join().unwrap();
    data += 2;
}
  • 解释:这里声明了一个可变变量data,多个线程(这里虽然只启动了一个线程,但如果有多个线程类似操作也会出现问题)可以访问并修改它。Rust默认变量在多线程间访问是不安全的,由于没有同步机制(如锁),不同线程对data的读写操作可能会交错,导致结果不可预测,这就是竞态条件。
  1. 使用Rc(引用计数)在多线程间共享数据
    • 代码模式
use std::rc::Rc;
fn main() {
    let shared_data = Rc::new(0);
    let cloned_data = Rc::clone(&shared_data);
    std::thread::spawn(move || {
        let _ = cloned_data;
    }).join().unwrap();
    let _ = shared_data;
}
  • 解释Rc本身不是线程安全的,它通过引用计数来管理内存。在多线程环境下,多个线程同时操作Rc的引用计数可能会导致计数错乱,进而可能出现内存释放问题或数据访问冲突,引发竞态条件。
  1. 未正确使用Mutex(互斥锁)
    • 代码模式
use std::sync::{Mutex, Arc};
fn main() {
    let data = Arc::new(Mutex::new(0));
    let cloned_data = Arc::clone(&data);
    std::thread::spawn(move || {
        let mut guard = cloned_data.lock().unwrap();
        *guard += 1;
    }).join().unwrap();
    let mut guard = data.lock().unwrap();
    *guard += 2;
}
  • 解释:虽然使用了Mutex来保护共享数据,但如果在实际应用中,没有正确处理MutexGuard(比如提前释放锁、在锁未获取成功时继续操作共享数据等),就可能导致多个线程同时访问共享数据,引发竞态条件。例如,如果在获取锁失败时没有合适的重试逻辑或处理方式,其他线程可能在该线程认为已获取锁时也获取锁并操作数据。