Rust多线程读写变量问题:超市队列模拟程序异常排查
Rust超市队列并发问题的修复
你的问题核心是第一个线程一直持有Mutex锁,导致第二个线程完全无法获取锁执行代码。
问题原因
第一个线程里,aux是MutexGuard类型,它的作用域覆盖了整个loop迭代——从调用lock()开始,直到thread::sleep(3秒)结束、整个循环块执行完毕,锁才会被释放。而Mutex是独占锁,第二个线程会一直卡在queue.lock()这一步,根本没机会进入后续逻辑,自然打不出"AUX state"的日志。
Rust的MutexGuard是RAII机制实现的,只有当它离开当前作用域时,才会自动调用drop释放锁。你原来的代码里,sleep是在锁持有期间执行的,这完全没必要,还会导致锁被长时间占用。
修复代码
把锁的持有范围缩小到仅操作队列的阶段,用一对额外的大括号限制aux的作用域,让锁在sleep前就释放:
use std::sync::{Arc, Mutex}; use std::thread; use std::time::Duration; use rand::Rng; fn print_queue(queue: &Vec<char>) { println!("Queue: {:?}", queue); } fn main() { let queue = Arc::new(Mutex::new(Vec::<char>::new())); let queue1 = Arc::clone(&queue); thread::spawn(move || loop { // 用大括号缩小锁的作用域 { let mut aux = queue1.lock().unwrap(); aux.push('x'); print_queue(&aux); } // 这里aux离开作用域,锁被自动释放 thread::sleep(Duration::from_secs(3)); }); let queue2 = Arc::clone(&queue); thread::spawn(move || loop { { let mut aux = queue2.lock().unwrap(); println!("AUX state: {:?}", aux); if !aux.is_empty() { aux.pop(); } print_queue(&aux); } // 锁在这里释放 let mut rng = rand::thread_rng(); thread::sleep(Duration::from_secs(rng.gen_range(1..10))); }); // 主线程需保持运行,否则子线程会被强制终止 thread::sleep(Duration::from_secs(30)); }
额外注意点
- 第二个线程建议单独clone一份
Arc实例,避免后续可能出现的所有权混淆问题; - 主线程必须添加足够长的sleep逻辑,否则主线程退出后所有子线程会被立即终止,无法看到完整的并发执行效果。
内容的提问来源于stack exchange,提问作者Erik
相关产品推荐
相关产品推荐

