我相信这是因为Rust没有运行您的
我在下面为我的问题创建了简化版,我有一个Bag
结构和Item
结构。我想在item_action
中的每个item
上从Bag中生成10个执行item_list
方法的线程,并在两个项目的属性都在bag的attributes
中时打印一条语句。
use std::sync::{Mutex,Arc}; use std::thread; #[derive(Clone, Debug)] struct Bag{ attributes: Arc<Mutex<Vec<usize>>> } impl Bag { fn new(n: usize) -> Self { let mut v = Vec::with_capacity(n); for _ in 0..n { v.push(0); } Bag{ attributes:Arc::new(Mutex::new(v)), } } fn item_action(&self, item_attr1: usize, item_attr2: usize) -> Result<(),()> { if self.attributes.lock().unwrap().contains(&item_attr1) || self.attributes.lock().unwrap().contains(&item_attr2) { println!("Item attributes {} and {} are in Bag attribute list!", item_attr1, item_attr2); Ok(()) } else { Err(()) } } } #[derive(Clone, Debug)] struct Item{ item_attr1: usize, item_attr2: usize, } impl Item{ pub fn new(item_attr1: usize, item_attr2: usize) -> Self { Item{ item_attr1: item_attr1, item_attr2: item_attr2 } } } fn main() { let mut item_list: Vec<Item> = Vec::new(); for i in 0..10 { item_list.push(Item::new(i, (i+1)%10)); } let bag: Bag= Bag::new(10); //create 10 attributes let mut handles = Vec::with_capacity(10); for x in 0..10 { let bag2 = bag.clone(); let item_list2= item_list.clone(); handles.push( thread::spawn(move || { bag2.item_action(item_list2[x].item_attr1, item_list2[x].item_attr2); }) ) } for h in handles { println!("Here"); h.join().unwrap(); } }
运行时,我只有一行,程序只是在那儿停了下来而没有返回。
:Item attributes 0 and 1 are in Bag attribute list!
我可以知道出了什么问题吗?请参阅Playground中的代码>
更新
根据@loganfsmyth的建议,该程序现在可以返回...,但仍然只打印上述一行。我希望它打印10,因为我的item_list
有10个项目。不知道我的线程逻辑是否正确。
我在调用println!("Here");
所有线程时都添加了join
。而且我可以看到Here
被打印了10次,但不是item_action
的实际日志
我在下面为我的问题创建了简化版,我有一个Bag结构和Item结构。我想在item_list中的每个项目上产生10个从Bag执行item_action方法的线程,然后...
我相信这是因为Rust没有运行您的
if self.attributes.lock().unwrap().contains(&item_attr1) || self.attributes.lock().unwrap().contains(&item_attr2) {
按您期望的顺序表达。目前,Rust中子表达式的求值顺序是不确定的。看来正在发生的事情实际上是您最终得到了
const condition = { let lock1 = self.attributes.lock().unwrap(); let lock2 = self.attributes.lock().unwrap(); lock1.contains(&item_attr1) || lock2.contains(&item_attr2) }; if condition {
这导致您的代码陷入僵局。
您应该写:
let attributes = self.attributes.lock().unwrap();
if attributes.contains(&item_attr1) ||
attributes.contains(&item_attr2) {
所以只有一把锁。
如果您使用RwLock
或RwLock
而不是ReentrantMutex
,您的代码也将照常工作,因为它们允许同一线程对数据具有多个不可变的引用。
我相信这是因为Rust没有运行您的