在由互斥锁定的结构中访问两个向量[duplicate]

问题描述 投票:4回答:2

这个问题在这里已有答案:

我有一个带有两个向量的结构,它在Arc<Mutex<TwoArrays>>中通过函数传递。

pub struct TwoArrays {
    pub a: Vec<i32>,
    pub b: Vec<i32>,
}

fn add_arrays(mut foo: Arc<Mutex<TwoArrays>>) {
    let mut f = foo.lock().unwrap();
    //Loop A: compiles
    for i in 0..f.a.len() {
        for j in 0..f.b.len() {
            f.b[j] += f.a[i];
        }
    }
    //Loop B: does not compile
    for i in f.a.iter() {
        for j in 0..f.b.len() {
            f.b[j] += i;
        }
    }
}

当我创建一个使用迭代器的循环,并在内部写入另一个循环(循环B)时,编译器会抱怨:

error[E0502]: cannot borrow `f` as mutable because it is also borrowed as immutable

循环A编译。

  • 为什么f上有不可变的借款?
  • 我可以让它只是单独借用每个数组吗?也就是说,f.b的可变借款和f.a的不变借款?
  • 当我直接通过TwoArrays时,为什么不会发生这种情况?它只发生在我作为Arc<Mutex<TwoArrays>>传递它
rust
2个回答
4
投票

当你打开LockResult时,你得到一个MutexGuard,而不是直接TwoArrays。你可以使用它,好像它是一个TwoArrays,因为它实现了DerefDerefMut

当你尝试编写2个循环时,你会尝试同时使用derefderef_mut:这是不可能的:

pub struct TwoArrays {
    pub a: Vec<i32>,
    pub b: Vec<i32>,
}

fn add_arrays(mut foo: Arc<Mutex<TwoArrays>>) {
    let mut f = foo.lock().unwrap();

    //Loop B: does not compile
    for i in f.a.iter() {
          //  ^~~~~~~~~~~~~~~~~~~ Implicit call to `deref` here.
        for j in 0..f.b.len() {
          //         ^~~~~~~~~~~~ Another implicit call to `deref` here.
            f.b[j] += i;
          // ^~~~~~~~~~~~~~~~~~~~ Implicit call to `deref_mut` here.
        }
    }
}

如果你在做循环之前有一次deref_mut,一切正常:

use std::{sync::{Arc, Mutex}, ops::DerefMut};

pub struct TwoArrays {
    pub a: Vec<i32>,
    pub b: Vec<i32>,
}

fn add_arrays(foo: &mut Arc<Mutex<TwoArrays>>) {
    let mut mutex_guard = foo.lock().unwrap();
    let real_two_arrays = mutex_guard.deref_mut();

    for i in &mut real_two_arrays.a {
        for j in &real_two_arrays.b {
            *i += *j;
        }
    }
}

1
投票

您可以在结构中访问两个向量,如下所示:

use std::mem;

#[derive(Debug)]
pub struct TwoArrays {
    pub a: Vec<i32>,
    pub b: Vec<i32>,
}

fn add_arrays(mut foo: TwoArrays) {
    let a = foo.a.clone();
    let mut b = foo.b.clone();

    for i in a.iter() {
        let mut index = 0;
        for _j in b.iter_mut() {
            let mut new_value = i.clone() + foo.b[index as usize].clone();
            mem::swap(&mut foo.b[index as usize], &mut new_value);
            index = index + 1;
        }
    }

    println!("Arrays A: {:?}", &foo.a);
    println!("Arrays A: {:?}", &foo.b);
}

fn main() {
    let a = vec![1i32, 2i32, 3i32];
    let b = vec![4i32, 5i32, 6i32];
    let two_arrays = TwoArrays { a, b };
    // let foo = Arc::new(Mutex::new(two_arrays));

    add_arrays(two_arrays);
}

Playground

为什么有f的不可变借款?

因为你试图用iter()迭代它而不是iter_mut()

当我直接传递TwoArrays时,为什么不会发生这种情况?它只发生在我作为Arc<Mutex<TwoArrays>>传递它

您可以将其作为裸结构传递,而无需使用带示例代码的Arc<Mutex<>>

如果您坚持使用Arc<Mutex<>>通过原子引用传递相同的对象,则可以将函数签名更改为以下内容:

fn add_arrays(mut foo: Arc<Mutex<TwoArrays>>)

你需要lock()并从Arc获得以下参考:

let foo = foo.lock().unwrap();

Playground With Arc Usage

© www.soinside.com 2019 - 2024. All rights reserved.