实际上,您自己回答了您的问题,所有需要在线程之间共享的闭包都需要
Sync
Rayon的API只要求
同步
通过特性界限。例如,请参见
documentation of
ParallelIterator::map()
,它将方法指定为
fn map<F, R>(self, map_op: F) -> Map<Self, F> where
F: Fn(Self::Item) -> R + Sync + Send,
R: Send,
这里没有任何更深层次的魔力,每当Rayon以一种需要它的方式使用一个闭包时,
同步
例如,通过将其传递给较低级别的API,Rayon使用
同步
性状结合。这反过来又确保了闭包中存储的所有内容
同步
,所以你不能储存任何
RefCell
在结尾处。
在这种情况下,您还可以向编译器请求解释。例如,如果您试图编译此代码
use std::cell::RefCell;
use rayon::prelude::*;
fn main() {
let c = RefCell::new(5);
let _ = [1, 2, 3]
.par_iter()
.map(|i| i * *c.borrow())
.sum();
}
你会得到这个错误(
playground
)
error[E0277]: `std::cell::RefCell<i32>` cannot be shared between threads safely
--> src/main.rs:10:10
|
10 | .map(|i| i * *c.borrow())
| ^^^ `std::cell::RefCell<i32>` cannot be shared between threads safely
|
= help: within `[closure@src/main.rs:10:14: 10:33 c:&std::cell::RefCell<i32>]`, the trait `std::marker::Sync` is not implemented for `std::cell::RefCell<i32>`
= note: required because it appears within the type `&std::cell::RefCell<i32>`
= note: required because it appears within the type `[closure@src/main.rs:10:14: 10:33 c:&std::cell::RefCell<i32>]`
不幸的是,编译器没有直接提到
map()
它仍然向您指出相关的方法,并解释它期望闭包是
同步
以及为什么没有。