MST

星途 面试题库

面试题:Rust线程模型中如何安全地共享可变状态

在Rust线程模型里,我们知道直接共享可变状态可能会导致数据竞争。请描述如何利用 `Mutex` 或者 `RwLock` 来安全地在多个线程间共享可变状态,并给出一个简单的代码示例。
43.2万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试

使用Mutex在多个线程间共享可变状态

Mutex(互斥锁)是一种同步原语,它通过在任何时刻只允许一个线程访问共享数据来防止数据竞争。当一个线程想要访问共享数据时,它必须先获取Mutex的锁。如果锁已经被其他线程持有,该线程将被阻塞,直到锁被释放。

以下是一个简单的代码示例:

use std::sync::{Arc, Mutex};
use std::thread;

fn main() {
    // 使用Arc来允许在多个线程间共享Mutex
    let counter = Arc::new(Mutex::new(0));
    let mut handles = vec![];

    for _ in 0..10 {
        let counter = Arc::clone(&counter);
        let handle = thread::spawn(move || {
            let mut num = counter.lock().unwrap();
            *num += 1;
        });
        handles.push(handle);
    }

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

    println!("Final counter value: {}", *counter.lock().unwrap());
}

使用RwLock在多个线程间共享可变状态

RwLock(读写锁)允许多个线程同时进行读操作,但只允许一个线程进行写操作。当有线程持有写锁时,其他线程无论是读还是写都将被阻塞。这在读取操作远远多于写入操作的场景下能提高性能。

以下是一个简单的代码示例:

use std::sync::{Arc, RwLock};
use std::thread;

fn main() {
    let data = Arc::new(RwLock::new(String::from("initial value")));
    let mut handles = vec![];

    // 启动一些读线程
    for _ in 0..5 {
        let data = Arc::clone(&data);
        let handle = thread::spawn(move || {
            let read_data = data.read().unwrap();
            println!("Read: {}", read_data);
        });
        handles.push(handle);
    }

    // 启动一个写线程
    let data = Arc::clone(&data);
    let write_handle = thread::spawn(move || {
        let mut write_data = data.write().unwrap();
        *write_data = String::from("new value");
    });
    handles.push(write_handle);

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

    println!("Final data: {}", *data.read().unwrap());
}