【发布时间】:2020-04-14 09:29:32
【问题描述】:
在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::new(giga_map)传入一个Arc<GigabyteMap>,这是一个指向已移动到堆中的GigabyteMap的智能指针。当我们调用glossary.clone() 时,我们正在复制Arc智能指针,而不是整个GigabyteMap。这相当于增加引用计数。通过此更改,程序可以编译并运行,因为它不再依赖于引用生命周期。 只要任何线程拥有Arc<GigabyteMap>,它就会使地图保持活动状态,即使父线程提前退出。不会有任何数据竞争,因为Arc中的数据是不可变的。
在下一节中,他们展示了用 Rayon 重写的内容,
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(())) }
您可以在重写为使用 Rayon 的部分中看到它接受 &GigabyteMap 而不是 Arc<GigabyteMap>。他们没有解释这是如何工作的。为什么 Rayon 不需要 Arc<GigabyteMap>? Rayon 如何不接受直接推荐?
【问题讨论】:
-
看来How can I pass a reference to a stack variable to a thread? 的答案可能会回答您的问题。如果没有,请edit您的问题来解释差异。否则,我们可以将此问题标记为已回答。
标签: rust reference-counting lifetime-scoping