You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Serde序列化Arc<RwLock>时如何保留字段的内存共享关系

问题根源

默认Serde的Serialize/Deserialize派生实现对Arc<T>的处理是直接序列化T的内容,不会记录多个Arc指向同一块内存的关联关系。反序列化时每个Arc<RwLock<f64>>字段都会独立创建新的内存实例,自然就失去了共享特性。

解决方案

方案1:优化结构体设计(最推荐,无额外开销)

如果两个字段本质就是同一个值的共享引用,完全可以只存储一份基础的Arc,对外提供访问方法返回克隆即可,完全兼容原有使用逻辑:

use serde::{Serialize, Deserialize};
use std::sync::{Arc, RwLock};

#[derive(Serialize, Deserialize)]
struct Container {
    inner: Arc<RwLock<f64>>,
}

impl Container {
    // 对外提供和原有结构兼容的访问接口
    pub(crate) fn ref0(&self) -> Arc<RwLock<f64>> {
        self.inner.clone()
    }
    pub(crate) fn ref1(&self) -> Arc<RwLock<f64>> {
        self.inner.clone()
    }

    // 如果需要直接赋值也可以提供对应的setter方法
    pub(crate) fn set_val(&self, new_val: f64) {
        *self.inner.write().unwrap() = new_val;
    }
}

序列化时只会存储一份值,反序列化后两个访问方法返回的都是同一个Arc的克隆,天然保持内存共享。

方案2:保留原有结构体字段,手动实现序列化/反序列化逻辑

如果必须保留ref0、ref1两个公开字段的结构,可以手动实现两个Serde trait,序列化时仅存一份值,反序列化时直接克隆Arc赋值给两个字段:

use serde::{Serialize, Serializer, Deserialize, Deserializer};
use std::sync::{Arc, RwLock};

struct Container {
    pub(crate) ref0: Arc<RwLock<f64>>,
    pub(crate) ref1: Arc<RwLock<f64>>
}

impl Serialize for Container {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        // 只需要序列化一次共享的值即可
        self.ref0.read().unwrap().serialize(serializer)
    }
}

impl<'de> Deserialize<'de> for Container {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        let val = f64::deserialize(deserializer)?;
        let base_arc = Arc::new(RwLock::new(val));
        Ok(Self {
            ref0: base_arc.clone(),
            ref1: base_arc,
        })
    }
}

如果你的场景存在跨多个结构体的共享Arc引用,需要全局追踪引用关系,可以使用serde_with库的Arc序列化扩展开启引用计数追踪能力,单结构体内部共享的场景用上述两个方案足够,无需引入额外依赖。


内容的提问来源于stack exchange,提问作者Christian Potts

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 11:15:06