所以,这不起作用:
use std::comm;
#[deriving(Show)]
struct St { v: u8 }
fn main() {
let mut foo:Vec<St> = Vec::new();
for i in range(0u8, 10) {
foo.push(St { v: i });
}
{
let mut foo_slice = foo.as_mut_slice();
let (f1, f2) = foo_slice.split_at_mut(5);
let (sl, rx):(Sender<Option<&mut [St]>>, Receiver<Option<&mut [St]>>) = comm::channel();
let (sx, rl):(Sender<bool>, Receiver<bool>) = comm::channel();
spawn(proc() {
loop {
let v = rx.recv();
match v {
Some(v) => {
v[0].v = 100u8;
sx.send(true);
},
None => {
sx.send(false);
break;
}
}
}
});
sl.send(Some(f1));
sl.send(Some(f2));
sl.send(None);
println!("{}", rl.recv());
println!("{}", rl.recv());
println!("{}", rl.recv());
}
println!("{}", foo);
}
...因为:
sl.send(Some(f1));
sl.send(Some(f2));
sl.send(None);
推断变量f1和f2必须是'静态的,因为任务可能比它正在运行的函数更长。这反过来意味着foo必须是'静态的,而不是'a,这是main的生命周期( )。
因此有些奇怪的错误:
<anon>:14:27: 14:30 error: `foo` does not live long enough
<anon>:14 let mut foo_slice = foo.as_mut_slice();
^~~
note: reference must be valid for the static lifetime...
<anon>:6:11: 46:2 note: ...but borrowed value is only valid for the block at 6:10
<anon>:6 fn main() {
<anon>:7
<anon>:8 let mut foo:Vec<St> = Vec::new();
<anon>:9 for i in range(0u8, 10) {
<anon>:10 foo.push(St { v: i });
<anon>:11 }
所以,为了解决这个问题,我认为使用Box&lt; Vec&lt; Foo&gt;&gt;可能是解决方案,但即使这样,创建的切片也将具有本地生命周期。
我可以使用不安全的代码来转换生命周期(这确实有效),但有没有办法安全地做同样的事情?
答案 0 :(得分:8)
Rust会阻止您对多个任务中的相同值进行可变访问,因为这会导致数据争用。具体来说,任务不能将指针(包括切片)借用到另一个任务所拥有的值。
要允许多个任务访问同一个对象,您应该使用Arc<T>
。要提供对该对象的可变访问权限,请在Arc
:Arc<RefCell<T>>
中添加RefCell<T>
。至于那个T
,你不能像我刚才解释的那样使用切片类型。我建议您创建2个不同的Arc<RefCell<Vec<St>>>
个对象,在频道上发送Arc<RefCell<Vec<St>>>
的克隆,并在任务完成后加入Vec
。
通常,在进行并行算法时,应避免改变共享状态。这会导致性能不佳,因为系统需要使内核中的内存缓存无效。如果可能,请考虑让任务分配并保持其结果直到完成,并通过通道发送完整的结果,而不仅仅是bool
。
修改强>
我们可以根据所有权重新制定您的初始计划,以了解为什么它不合理。调用main
的堆栈框架拥有foo
Vec
。 foo_slice
,f1
和f2
借用Vec
。你产生了一个任务。 该任务可能比main
的调用框架更长,甚至比生成它的任务更长。因此,发送对受限于堆栈帧的值的引用是非法的。这就是为什么借用指针({1}}除外)不符合Send
。
拳击&'static T
不会改变任何内容,因为堆栈帧仍然拥有Vec
,因此从函数返回将删除框及其内容。
编译器无法验证任务是否不会超过您发送对任务的引用值的所有者。如果您确定该任务将在您提供的引用无效之前终止,您可以使用transmute
来欺骗生命周期,但这是不安全的。