人造丝为什么不需要Arc <>?

问题描述 投票:0回答:1

Programming Rust的第465页上,您可以找到代码和说明(我加了强调)

use std::sync::Arc;

fn process_files_in_parallel(filenames: Vec<String>,
                             glossary: Arc<GigabyteMap>)
    -> io::Result<()>
{
    ...
    for worklist in worklists {
        // This call to .clone() only clones the Arc and bumps the
        // reference count. It does not clone the GigabyteMap.
        let glossary_for_child = glossary.clone();
        thread_handles.push(
            spawn(move || process_files(worklist, &glossary_for_child))
        );
    }
    ...
}

我们已经更改了词汇表的类型:要并行运行分析,调用者必须通过执行Arc<GigabyteMap>来传递GigabyteMap,该智能指针指向已移入堆中的Arc::new(giga_map)。当我们调用lossary.clone()时,我们正在复制Arc智能指针,而不是整个GigabyteMap。这相当于增加参考计数。进行此更改后,程序将编译并运行,因为它不再依赖于参考生存期。 只要任何线程拥有一个Arc<GigabyteMap>,它都会使映射保持活动状态,即使父线程提早解救了。不会有任何数据争用,因为Arc中的数据是不可变的。

在下一节中,他们显示了用人造丝重写的内容,

extern crate rayon;

use rayon::prelude::*;

fn process_files_in_parallel(filenames: Vec<String>, glossary: &GigabyteMap)
    -> io::Result<()>
{
    filenames.par_iter()
        .map(|filename| process_file(filename, glossary))
        .reduce_with(|r1, r2| {
            if r1.is_err() { r1 } else { r2 }
        })
        .unwrap_or(Ok(()))
}

您可以在改写为使用人造丝的部分中看到,它接受&GigabyteMap而不是Arc<GigabyteMap>。他们没有解释这是如何工作的吗?我想知道为什么Ryan不需要Arc<GigabyteMap>? Rayan如何摆脱接受直接引用的麻烦?

rust automatic-ref-counting lifetime-scoping
1个回答
0
投票

Rayon可以保证迭代器不会超过当前的堆栈帧,这与我在第一个代码示例中假设的是thread::spawn不同。具体而言,引擎盖下的par_iter使用类似于Rayon的scope函数的功能,该函数允许生成“附加”到堆栈的工作单元,并在堆栈结束之前加入。

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