从clone()开始,Arc的生命周期不够长

时间:2016-05-22 21:42:59

标签: thread-safety rust

我试图创建一个可能在线程之间共享的参数结构。它有一个名为layer_storage的成员,一些成员需要进行变异。我尝试了以下代码,但是收到错误消息称克隆的Arc活不了多久。在添加Arc<Mutex<>>之前,该成员工作正常。

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

#[derive(Clone)]
pub struct Params {
    pub optional: Vec<f32>,
}

pub struct ParamManager {
    layer_storage: Arc<Mutex<Vec<Params>>>,
}

impl Default for ParamManager {
    fn default() -> ParamManager {
        ParamManager {
            layer_storage: Arc::new(Mutex::new(vec![Params { optional: vec![1.0f32, 2.0f32] },
                                                    Params { optional: vec![3.0f32, 4.0f32] }])),
        }
    }
}

impl ParamManager {
    pub fn get_mut_params(&mut self, layer_index: usize) -> &mut Params {
        let layers_arc = self.layer_storage.clone();
        let layers = layers_arc.get_mut().unwrap();
        // tried this initially:
        // let layers = self.layer_storage.clone().get_mut().unwrap();
        assert!(layers.len() - 1 >= layer_index);
        &mut layers[layer_index]
    }
}

fn main() {
    let mut bla = ParamManager::default();
    let i = bla.get_mut_params(0);
}

Playground

2 个答案:

答案 0 :(得分:2)

正如@Shepmaster所说,你不能从Arc<Mutex<T>>返回对get_mut_params内某些内容的引用;这是你从中获得的保证之一!

在一些情况下可行的一种解决方案是将功能内部化;而不是返回一个可变引用,取一个给出可变引用的闭包:

impl ParamManager {
    pub fn with_mut_params<F>(&mut self, layer_index: usize, mut f: F)
                     where F: FnMut(&mut Params) {
        let layers_arc = self.layer_storage.clone();
        let layers = layers_arc.lock().unwrap();
        f(&mut layers[layer_index]);
    }
}

fn main() {
    let mut bla = ParamManager::default();

    // Context used by the closure
    let some_var: i32 = 7;
    let other_var: mut MyContext = do_something();

    bla.with_mut_params(0, |i| {
       // do stuff with i
       ...
       // A closure has access to surrounding variables
       other_var.foo(i, some_var);
    });

}

答案 1 :(得分:1)

我认为编译器在你的情况下是正确的。

这里有两个明显的错误:

  1. layers_arc值一直存在到块结束,然后它的析构函数将递减引用计数器并可能会丢弃整个值。或者它可以随时在其他线程中删除。因此,返回指向其内容的指针是违法的。

  2. Mutex::get_mut方法需要&mut self,而无法直接从Arc获取。

  3. 所以你必须以某种方式重构你的代码。例如,您可以使用Arc<Mutex>保护向量中的每个单独项目,并使用.clone()按值返回。