MST

星途 面试题库

面试题:Rust 同步函数调用中的内存管理及锁机制应用

在 Rust 同步函数调用过程中,内存管理是如何配合函数调用逻辑的?详细描述锁机制在同步函数并发调用场景下,是怎样保证数据一致性的,并结合实际代码示例说明。
38.0万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试

Rust 同步函数调用中的内存管理与函数调用逻辑配合

  1. 栈内存分配:在 Rust 中,当一个同步函数被调用时,函数的参数和局部变量通常在栈上分配内存。例如:
fn add_numbers(a: i32, b: i32) -> i32 {
    let sum = a + b;
    sum
}

这里 absum 都在栈上分配内存。当函数返回时,栈上为这些变量分配的内存会被自动释放。 2. 堆内存分配:如果函数中使用了需要在堆上分配内存的数据结构,如 BoxVec 等,那么堆内存会根据需要进行分配。例如:

fn create_vector() -> Vec<i32> {
    let mut vec = Vec::new();
    for i in 0..10 {
        vec.push(i);
    }
    vec
}

Vec 在堆上分配内存来存储元素。当 create_vector 函数返回 vec 时,调用者会接管 vec 的所有权,并且在 vec 离开作用域时,其堆内存会被释放。

锁机制在同步函数并发调用场景下保证数据一致性

  1. Mutex(互斥锁)Mutex 是 Rust 中常用的锁机制,用于保护共享数据。只有获得锁的线程才能访问被保护的数据,其他线程必须等待锁的释放。
use std::sync::{Mutex, Arc};
use std::thread;

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

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

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

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

在这个例子中,Mutex 保护了一个共享的整数 data。每个线程在访问和修改 data 之前,必须先通过 lock 方法获取锁。如果锁不可用,线程会被阻塞,直到锁被释放。这样就保证了在同一时间只有一个线程能修改 data,从而确保数据一致性。 2. RwLock(读写锁):适用于读多写少的场景。多个线程可以同时获取读锁来读取数据,但只有一个线程可以获取写锁来修改数据。

use std::sync::{RwLock, Arc};
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_clone = Arc::clone(&data);
        let handle = thread::spawn(move || {
            let read_data = data_clone.read().unwrap();
            println!("Read data: {}", read_data);
        });
        handles.push(handle);
    }

    let write_handle = thread::spawn(move || {
        let mut write_data = data.write().unwrap();
        *write_data = String::from("new value");
    });

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

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

这里 RwLock 保护了一个字符串 data。多个读线程可以同时获取读锁读取数据,而写线程在修改数据前获取写锁,写锁会阻止其他读线程和写线程获取锁,从而保证数据一致性。