MST

星途 面试题库

面试题:Rust并行编程中的线程安全

在Rust并行编程中,如何确保数据在线程间共享时的线程安全性?请举例说明使用`Mutex`或`RwLock`来实现线程安全的场景。
15.6万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试

在Rust并行编程中,确保数据在线程间共享时的线程安全性,通常可以使用以下几种方式:

  1. Mutex(互斥锁)
    • Mutex(Mutual Exclusion的缩写)用于保护共享数据,确保同一时间只有一个线程可以访问数据。
    • 当一个线程想要访问被Mutex保护的数据时,它必须先获取锁。如果锁已经被其他线程持有,该线程会被阻塞,直到锁被释放。
    • 例如,假设有一个共享的计数器,多个线程需要对其进行递增操作:
use std::sync::{Arc, Mutex};
use std::thread;

fn main() {
    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());
}
- 在这个例子中,`Arc`(原子引用计数)用于在多个线程间共享`Mutex`实例,`Mutex`保护着计数器`num`。每个线程通过`lock()`方法获取锁,对计数器进行递增操作,操作完成后锁会自动释放(因为`lock()`返回的是一个实现了`Drop` trait的智能指针,离开作用域时会自动释放锁)。

2. 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 value = data.read().unwrap();
            println!("Read value: {}", value);
        });
        handles.push(handle);
    }

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

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

    let final_value = data.read().unwrap();
    println!("Final value: {}", final_value);
}
- 在这个例子中,`Arc`用于共享`RwLock`实例,读线程通过`read()`方法获取读锁,写线程通过`write()`方法获取写锁。读锁允许多个线程同时读取数据,而写锁会阻止其他读线程和写线程,直到写操作完成。