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

如何在组合关系的结构体间共享变量?(生命周期错误)

解决方案:通过共享所有权与内部可变性实现状态注入

直接在EventProcessor中持有MemoryEventStore容器的引用会违反Rust的借用规则——你无法同时拥有一个值的所有权和它的可变引用,这会导致悬垂引用风险或同时存在多个可变引用的冲突。要实现构造时注入共享状态,需借助共享所有权和内部可变性机制。

方案1:多线程安全场景(Arc)

如果你的代码需要支持多线程,使用Arc(原子引用计数)实现共享所有权,Mutex保证线程安全的可变访问:

use std::collections::HashMap;
use std::sync::{Arc, Mutex};

pub struct MemoryEventStore {
    created_links_event_stream: Arc<Mutex<Vec<LinkCreatedEvent>>>,
    link_clicked_event_stream: Arc<Mutex<Vec<LinkClickedEvent>>>,
    aggregated_short_links: Arc<Mutex<HashMap<String, String>>>,
    aggregated_clicks: Arc<Mutex<HashMap<String, u64>>>,
    event_processor: EventProcessor,
}

impl MemoryEventStore {
    pub fn new() -> Self {
        let s1 = Arc::new(Mutex::new(Vec::new()));
        let s2 = Arc::new(Mutex::new(Vec::new()));
        let agg1 = Arc::new(Mutex::new(HashMap::new()));
        let agg2 = Arc::new(Mutex::new(HashMap::new()));
        
        let ep = EventProcessor::new(
            Arc::clone(&s1),
            Arc::clone(&s2),
            Arc::clone(&agg1),
            Arc::clone(&agg2),
        );
        
        Self {
            created_links_event_stream: s1,
            link_clicked_event_stream: s2,
            aggregated_short_links: agg1,
            aggregated_clicks: agg2,
            event_processor: ep,
        }
    }

    // 对外暴露处理事件的方法
    pub fn process_events(&mut self) {
        self.event_processor.process();
    }
}

pub struct EventProcessor {
    created_links_event_stream: Arc<Mutex<Vec<LinkCreatedEvent>>>,
    link_clicked_event_stream: Arc<Mutex<Vec<LinkClickedEvent>>>,
    aggregated_short_links: Arc<Mutex<HashMap<String, String>>>,
    aggregated_clicks: Arc<Mutex<HashMap<String, u64>>>,
    created_links_stream_next_idx: usize,
    link_clicked_stream_next_idx: usize,
}

impl EventProcessor {
    fn new(
        s1: Arc<Mutex<Vec<LinkCreatedEvent>>>,
        s2: Arc<Mutex<Vec<LinkClickedEvent>>>,
        agg1: Arc<Mutex<HashMap<String, String>>>,
        agg2: Arc<Mutex<HashMap<String, u64>>>,
    ) -> Self {
        Self {
            created_links_event_stream: s1,
            link_clicked_event_stream: s2,
            aggregated_short_links: agg1,
            aggregated_clicks: agg2,
            created_links_stream_next_idx: 0,
            link_clicked_stream_next_idx: 0,
        }
    }

    fn process(&mut self) {
        // 处理新建链接事件
        {
            let s1 = self.created_links_event_stream.lock().unwrap();
            let mut agg1 = self.aggregated_short_links.lock().unwrap();
            let start = self.created_links_stream_next_idx;
            let end = s1.len();

            for i in start..end {
                let event = &s1[i];
                agg1.insert(event.slug.clone(), event.url.clone());
            }

            self.created_links_stream_next_idx = end;
        }

        // 处理链接点击事件
        {
            let s2 = self.link_clicked_event_stream.lock().unwrap();
            let mut agg2 = self.aggregated_clicks.lock().unwrap();
            let start = self.link_clicked_stream_next_idx;
            let end = s2.len();

            for i in start..end {
                let event = &s2[i];
                let last_value = agg2.get(&event.slug).unwrap_or(&0);
                agg2.insert(event.slug.clone(), last_value + 1);
            }

            self.link_clicked_stream_next_idx = end;
        }
    }
}

struct LinkCreatedEvent {
    url: String,
    slug: String,
}

struct LinkClickedEvent {
    slug: String,
}

fn main() {
    let mut store = MemoryEventStore::new();
    store.process_events();
}

方案2:单线程场景(Rc)

如果代码仅在单线程运行,使用Rc(单线程引用计数)+RefCell(单线程内部可变性)可以避免Mutex的性能开销:

只需将上述代码中的Arc<Mutex<T>>替换为Rc<RefCell<T>>,并调整锁的调用方式:

  • lock().unwrap() → borrow()(不可变访问)或borrow_mut()(可变访问)
  • Arc::clone → Rc::clone

核心逻辑与多线程版本一致,只是去掉了线程安全的同步开销。

关键原理说明

  • 共享所有权:Arc/Rc允许多个结构体同时拥有同一容器的所有权,避免了引用生命周期的限制。
  • 内部可变性:Mutex/RefCell突破了Rust编译时的可变规则,在运行时保证同一时间只有一个可变引用,既满足了状态修改需求,又保证了内存安全。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 19:37:12