面试题答案
一键面试挑战分析
- 共享状态访问:多个异步任务可能同时访问闭包内的共享状态,容易导致数据竞争。
- 生命周期管理:闭包在不同异步任务中被调用,需要确保闭包引用的状态在闭包使用期间一直有效,避免悬垂引用。
解决方案
Mutex
:用于保护共享状态,通过互斥锁保证同一时间只有一个任务能访问共享数据,防止数据竞争。Arc
:用于在多个任务间共享闭包,Arc
是引用计数智能指针,能保证数据在所有引用都消失后才被释放。async
/await
:确保异步操作按顺序执行,避免竞态条件。
具体实现代码
use std::sync::{Arc, Mutex};
use std::thread;
use futures::executor::block_on;
async fn async_fn() -> impl Fn() {
let shared_data = Arc::new(Mutex::new(0));
let data_clone = shared_data.clone();
move || {
let mut data = data_clone.lock().unwrap();
*data += 1;
println!("Data in closure: {}", *data);
}
}
fn main() {
let closure = block_on(async_fn());
let mut handles = vec![];
for _ in 0..10 {
let closure_clone = closure.clone();
let handle = thread::spawn(move || {
closure_clone();
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
}
在上述代码中:
Arc<Mutex<T>>
用于创建可在多线程间共享且线程安全的shared_data
。async_fn
返回一个闭包,闭包捕获了Arc<Mutex<T>>
的克隆,这样多个异步任务可以安全地访问共享数据。- 在闭包内部,通过
lock
获取锁来访问和修改共享数据,防止数据竞争。 - 在
main
函数中,通过block_on
执行异步函数获取闭包,然后在多个线程中调用闭包,展示了在多任务环境下闭包的正确使用。