面试题答案
一键面试Rust 同步函数调用中的内存管理与函数调用逻辑配合
- 栈内存分配:在 Rust 中,当一个同步函数被调用时,函数的参数和局部变量通常在栈上分配内存。例如:
fn add_numbers(a: i32, b: i32) -> i32 {
let sum = a + b;
sum
}
这里 a
、b
和 sum
都在栈上分配内存。当函数返回时,栈上为这些变量分配的内存会被自动释放。
2. 堆内存分配:如果函数中使用了需要在堆上分配内存的数据结构,如 Box
、Vec
等,那么堆内存会根据需要进行分配。例如:
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
离开作用域时,其堆内存会被释放。
锁机制在同步函数并发调用场景下保证数据一致性
- 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
。多个读线程可以同时获取读锁读取数据,而写线程在修改数据前获取写锁,写锁会阻止其他读线程和写线程获取锁,从而保证数据一致性。