Raz*_*can 12 concurrency multithreading reference-counting rust
我正在尝试在Rust中使用线程之间共享一个可变对象Arc,但是我收到了这个错误:
error[E0596]: cannot borrow data in a `&` reference as mutable
--> src/main.rs:11:13
|
11 | shared_stats_clone.add_stats();
| ^^^^^^^^^^^^^^^^^^ cannot borrow as mutable
Run Code Online (Sandbox Code Playgroud)
这是示例代码:
use std::{sync::Arc, thread};
fn main() {
let total_stats = Stats::new();
let shared_stats = Arc::new(total_stats);
let threads = 5;
for _ in 0..threads {
let mut shared_stats_clone = shared_stats.clone();
thread::spawn(move || {
shared_stats_clone.add_stats();
});
}
}
struct Stats {
hello: u32,
}
impl Stats {
pub fn new() -> Stats {
Stats { hello: 0 }
}
pub fn add_stats(&mut self) {
self.hello += 1;
}
}
Run Code Online (Sandbox Code Playgroud)
我能做什么?
She*_*ter 21
Arc 将自己描述为:
用于共享状态的原子引用计数包装器.
请注意,它是共享状态,而不是共享可变状态.对于共享可变状态,您可能希望Arc结合使用Arc:
use std::{
sync::{Arc, Mutex},
thread,
};
struct Stats;
impl Stats {
fn add_stats(&mut self, _other: &Stats) {}
}
fn main() {
let shared_stats = Arc::new(Mutex::new(Stats));
let threads = 5;
for _ in 0..threads {
let my_stats = shared_stats.clone();
thread::spawn(move || {
let mut shared = my_stats.lock().unwrap();
shared.add_stats(&Stats);
});
// Note: Immediately joining, no multithreading happening!
// THIS WAS A LIE, see below
}
}
Run Code Online (Sandbox Code Playgroud)
这很大程度上来自Arc文档.
如何在for之后使用shared_stats?(我说的是Stats对象).似乎shared_stats无法轻易转换为Stats.
这是正确的,一旦你把东西放进一个Mutex或者RwLock,你就无法将对象退出.你永远不会知道还有什么对共享状态的引用,所以你永远不知道是否可以安全地取回所有权.
你可以锁定它并获得一个可变或不可变的引用,就是它.
从Rust 1.15开始,可以获得价值.另请参阅我的其他答案.
它说没有多线程.为什么?
因为我感到困惑!:-)
在示例代码中,Atomic(a Mutex)的结果立即被删除,因为它没有存储在任何地方.当手柄掉落时,螺纹脱落,可能会或可能不会完成.我把它混淆了Arc,这是一个不稳定的API,在它被删除时加入.对困惑感到抱歉!
对于一些社论,我可能建议完全避免可变性:
use std::{ops::Add, thread};
#[derive(Debug)]
struct Stats(u64);
// Implement addition on our type
impl Add for Stats {
type Output = Stats;
fn add(self, other: Stats) -> Stats {
Stats(self.0 + other.0)
}
}
fn main() {
let threads = 5;
// Start threads to do computation
let threads: Vec<_> = (0..threads).map(|_| thread::spawn(|| Stats(4))).collect();
// Join all the threads, fail if any of them failed
let result: Result<Vec<_>, _> = threads.into_iter().map(|t| t.join()).collect();
let result = result.unwrap();
// Add up all the results
let sum = result.into_iter().fold(Stats(0), |i, sum| sum + i);
println!("{:?}", sum);
}
Run Code Online (Sandbox Code Playgroud)
在这里,我们保留对它的引用Mutex,然后等待所有线程完成.然后我们收集结果并将它们全部添加.这是常见的map-reduce模式.请注意,没有线程需要任何可变性,它都发生在主线程中.
| 归档时间: |
|
| 查看次数: |
2965 次 |
| 最近记录: |