在第十五章中,通过使用智能指针 Rc 来创建引用计数的值,以便拥有多所有者。让我们在这也这么
做看看会发生什么。将示例 16-14 中的 Mutex 封装进 Rc 中并在将所有权移入线程之前克隆了
Rc。
文件名: src∕main.rs
use std::rc::Rc;
use std::sync::Mutex;
use std::thread;
fn main() {
let counter = Rc::new(Mutex::new(0));
let mut handles = vec![];
for _ in 0…10 {
let counter = Rc::clone(&counter);
let handle = thread::spawn(move || {
let mut num = counter.lock().unwrap();
*num += 1;
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
println!(“Result: {}”, *counter.lock().unwrap());
}
示例 16-14: 尝试使用 Rc 来允许多个线程拥有 Mutex
再一次编译并⋯出现了不同的错误!编译器真是教会了我们很多!
$ cargo run
Compiling shared-state v0.1.0 (file:///projects/shared-state)
error[E0277]: Rc<Mutex<i32>>
cannot be sent between threads safely
–> src/main.rs:11:22
|
11 | let handle = thread::spawn(move || {
| ____________^^^^^^^^^^^^^-
| | |
| | Rc<Mutex<i32>>
cannot be sent between threads safely
12 | | let mut num = counter.lock().unwrap();
13 | |
14 | | *num += 1;
15 | | });
| |- within this [closure@src/main.rs:11:36: 15:10]
|
= help: within [closure@src/main.rs:11:36: 15:10]
, the trait Send
is not implemented for Rc<Mutex<i32>>
= note: required because it appears within the type [closure@src/main.rs:11:36: 15:10]
note: required by a bound in spawn
For more information about this error, try rustc --explain E0277
.
error: could not compile shared-state
due to previous error
哇哦,错误信息太长不看!这里是一些需要注意的重要部分:第一行错误表明 ‘ std:: rc :: Rc<std::sync::Mutex>‘ cannot be sent between threads safely。
编译器也告诉了我们原因 the trait bound ‘Send‘ is not satisfied。下一部分会讲到 Send:这是确保所
使用的类型可以用于并发环境的 trait 之一。
不幸的是,Rc 并不能安全的在线程间共享。当 Rc 管理引用计数时,它必须在每一个 clone 调用
时增加计数,并在每一个克隆被丢弃时减少计数。Rc 并没有使用任何并发原语,来确保改变计数的操
作不会被其他线程打断。在计数出错时可能会导致诡异的 bug,比如可能会造成内存泄漏,或在使用结束
之前就丢弃一个值。我们所需要的是一个完全类似 Rc,又以一种线程安全的方式改变引用计数的类型。
Rust从入门到实战系列一百九十三:多线程和多所有权
最新推荐文章于 2024-08-15 15:54:59 发布