Rust中如何实现带Arc<RwLock>的递归结构多所有者可修改?
问题原因
Arc<T>是共享所有权智能指针,默认仅能提供T的不可变访问,只有当引用计数为1时才能调用get_mut获取可变引用,你的场景下是多父节点共享子节点,引用计数必然大于1,不能用get_mut方法,必须通过RwLock的写锁实现内部可变性访问。- 你当前使用的是
async_std::sync::RwLock,不能直接通过get_mut获取内部值的可变引用,必须调用write()方法获取写锁。 - 原
Node结构体的node()方法使用了self作为入参,调用后会直接消耗掉Node实例,后续无法再访问该节点,属于设计缺陷。 - 模式匹配时直接写
NodeType::Network(mut content)会尝试转移枚举内部Network值的所有权,不符合只修改内部字段的需求。
修复步骤
第一步:修改Node的node()方法
将方法入参改为不可变借用,返回Arc的引用,避免消耗Node实例:
impl Node { // 其他方法保持不变 pub(crate) fn node(&self) -> &Arc<RwLock<NodeType>> { &self.node } }
第二步:修改main函数中的修改逻辑
通过RwLock写锁获取内部值的可变访问,模式匹配时使用可变借用:
// 获取节点的RwLock引用 let node_lock = agent0.subnet[0][2].node(); // 获取写锁:如果是异步执行环境,需要改为 let mut node_guard = node_lock.write().await; let mut node_guard = node_lock.write().unwrap(); // 匹配枚举类型,可变借用内部的Network实例 if let NodeType::Network(ref mut network) = *node_guard { // 向Network的子网追加新的Mesh节点 let new_mesh_node = Node::new(NodeType::Mesh(Mesh::new())); network.subnet[0].push(new_mesh_node); }
注意:如果你的代码运行在异步runtime中,
write()方法返回的是Future,需要加.await才能获取写锁;如果是同步场景,可以替换为std::sync::RwLock,直接调用write().unwrap()即可。
额外说明
该方案完全符合你的需求:没有发生深拷贝,仅通过Arc共享所有权,通过RwLock保证多线程环境下的安全修改,也支持多父节点引用同一个子节点的场景。
内容的提问来源于stack exchange,提问作者Christian Potts
相关产品推荐
相关产品推荐

