gpt4 book ai didi

multithreading - Rust:并发错误,程序在第一个线程后挂起

转载 作者:行者123 更新时间:2023-11-29 08:28:14 26 4
gpt4 key购买 nike

我在下面创建了我的问题的简化版本,我有一个 Bag 结构和 Item 结构。我想生成 10 个线程,在 item_list 中的每个 item 上从 Bag 执行 item_action 方法,如果两个项目的属性都在包的属性

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 的建议,程序现在可以返回...但仍然只打印 1 行,如上所示。我希望它打印 10,因为我的 item_list 有 10 个项目。不确定我的线程逻辑是否正确。

我在调用join所有线程时添加了println!("Here");。我可以看到 Here 打印了 10 次,而不是来自 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,您的代码也可以按原样工作或 ReentrantMutex而不是 Mutex,因为它们允许同一个线程对数据有多个不可变引用。

关于multithreading - Rust:并发错误,程序在第一个线程后挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58531550/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com