MST
星途 面试题库

面试题:Rust中线程间如何安全共享数据

在Rust并发编程里,线程间共享数据需要保证安全性。请描述至少两种在Rust中实现线程间安全共享数据的方式,并举例说明其使用场景和具体实现代码。
26.0万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试

1. 使用 ArcMutex

Arc(原子引用计数)用于在多个线程间共享数据,Mutex(互斥锁)用于保护数据的安全访问。

使用场景:适用于读多写少的场景,多个线程需要读取共享数据,偶尔会有线程进行写入操作。

具体实现代码

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

fn main() {
    let shared_data = Arc::new(Mutex::new(0));
    let mut handles = vec![];

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

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

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

2. 使用 RwLock

RwLock(读写锁)允许多个线程同时进行读操作,但只允许一个线程进行写操作。

使用场景:适合读操作远远多于写操作的场景,因为读操作不需要获取独占锁,性能更高。

具体实现代码

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

fn main() {
    let shared_data = Arc::new(RwLock::new(0));
    let mut handles = vec![];

    for _ in 0..10 {
        let data = Arc::clone(&shared_data);
        let handle = thread::spawn(move || {
            let num = data.read().unwrap();
            println!("Read value: {}", *num);
        });
        handles.push(handle);
    }

    let data = Arc::clone(&shared_data);
    let write_handle = thread::spawn(move || {
        let mut num = data.write().unwrap();
        *num += 1;
    });
    handles.push(write_handle);

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

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

3. 使用 Channel

通道用于在不同线程间传递数据,这是一种基于消息传递的并发模型。

使用场景:适合线程间需要进行数据传递和同步的场景,比如生产者 - 消费者模型。

具体实现代码

use std::sync::mpsc;
use std::thread;

fn main() {
    let (tx, rx) = mpsc::channel();

    let producer = thread::spawn(move || {
        for i in 0..10 {
            tx.send(i).unwrap();
        }
    });

    let consumer = thread::spawn(move || {
        for num in rx {
            println!("Received: {}", num);
        }
    });

    producer.join().unwrap();
    consumer.join().unwrap();
}