MST

星途 面试题库

面试题:Rust读写锁在并发场景下的基本应用

请描述在Rust中,如何使用读写锁(`RwLock`)来实现多个线程安全地读取和单个线程安全地写入共享数据。请给出一个简单的代码示例,并解释每一步的作用。
12.4万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试

在Rust中,RwLock允许我们实现多个线程安全地读取和单个线程安全地写入共享数据。以下是一个简单的代码示例及解释:

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

fn main() {
    // 创建一个包含共享数据的Arc<RwLock<T>>
    let data = Arc::new(RwLock::new(0));

    // 创建多个读取线程
    let mut read_handles = vec![];
    for _ in 0..10 {
        let data_clone = Arc::clone(&data);
        let handle = thread::spawn(move || {
            // 获取读锁,多个线程可以同时持有读锁
            let value = data_clone.read().unwrap();
            println!("Read value: {}", value);
        });
        read_handles.push(handle);
    }

    // 创建一个写入线程
    let write_handle = thread::spawn(move || {
        // 获取写锁,同一时间只能有一个线程持有写锁
        let mut value = data.write().unwrap();
        *value += 1;
        println!("Write value: {}", value);
    });

    // 等待所有读取线程完成
    for handle in read_handles {
        handle.join().unwrap();
    }

    // 等待写入线程完成
    write_handle.join().unwrap();
}

代码解释:

  1. 创建共享数据

    let data = Arc::new(RwLock::new(0));
    
    • Arc是原子引用计数智能指针,用于在多个线程间共享数据。
    • RwLock用于提供读写锁功能,内部包裹的数据类型为i32,初始值为0。
  2. 创建读取线程

    let mut read_handles = vec![];
    for _ in 0..10 {
        let data_clone = Arc::clone(&data);
        let handle = thread::spawn(move || {
            let value = data_clone.read().unwrap();
            println!("Read value: {}", value);
        });
        read_handles.push(handle);
    }
    
    • 使用Arc::clone复制Arc指针,使得每个线程都有自己的引用。
    • thread::spawn创建新线程,在每个线程中,通过data_clone.read().unwrap()获取读锁,多个线程可以同时持有读锁进行读取操作。
  3. 创建写入线程

    let write_handle = thread::spawn(move || {
        let mut value = data.write().unwrap();
        *value += 1;
        println!("Write value: {}", value);
    });
    
    • 同样使用thread::spawn创建新线程,通过data.write().unwrap()获取写锁,同一时间只能有一个线程持有写锁进行写入操作。
  4. 等待线程完成

    for handle in read_handles {
        handle.join().unwrap();
    }
    write_handle.join().unwrap();
    
    • 使用join方法等待所有读取线程和写入线程完成。