问题描述
我的应用程序分两个阶段工作:
- 创建了一个大型数据结构,其中涉及大量临时对象,并使用引用计数进行堆管理
- 将数据结构设置为只读,将所有仍在运行的数据停放,并将结果结构发送到另一个线程进行读取。
(为了更加具体,该应用程序是语言服务器,并且数据结构是处理的单个文件,这些文件是单线程处理的,但其结果必须跨线程传递。)
当前,我正在使用Arc<T>
来管理数据结构,但是由于阶段1既庞大又昂贵,并且是单线程的,所以我想将其切换为使用Rc<T>
。但是Rc
既不是Send
也不是Sync
,这是有充分的理由的,除非程序中基本上所有内容都使用线程安全的原语,否则我将无法发送数据结构或对其的引用。 / p>
我想说第二阶段开始后,我们不再需要引用计数了。线程1(所有者)不允许触摸引用计数,线程2(借款人)不允许克隆数据,只能查看数据,因此也不能触摸引用计数。我知道Rc
不会提供这组保证,因为您可以克隆给定共享引用的Rc
。此模式是否有安全的API?理想情况下,从阶段1到阶段2时,我不必复制任何数据。
这是一个玩具实现,只是在其中添加了一些代码。函数phase1()
在返回类型为T
的数据结构之前会产生大量垃圾,然后在另一线程上的phase2()
中以只读方式对其进行分析。如果您在此代码中将Arc
更改为Rc
,则会收到错误消息,因为它无法跨线程发送。
use std::sync::Arc;
use crossbeam::thread::scope; // uses the crossbeam crate for scoped threads
enum T { Nil,More(Arc<T>) }
fn phase1() -> T {
let mut r = T::Nil;
for i in 0..=5000 {
r = T::Nil;
for _ in 0..i { r = T::More(Arc::new(r)) }
}
r
}
fn phase2(mut t: &T) {
let mut n = 0;
while let T::More(a) = t {
n += 1;
t = a;
}
println!("length = {}",n); // should return length = 5000
}
fn main() {
let r = phase1();
scope(|s| { s.spawn(|_| phase2(&r)); }).unwrap();
}
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)