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

Rust中不使用Mutex实现线程间最新状态传递的方案

解决方案:无锁原子状态同步

针对你的实时线程无阻塞写入、Web线程获取最新状态的需求,推荐两种无锁方案,完全避免阻塞实时线程:

方案1:原子指针(AtomicPtr)- 适配非Copy类型的状态

适合硬件状态是复杂结构体、无法实现Copy的场景,通过原子替换堆内存指针实现无锁同步,写入操作完全无阻塞。

代码示例

use std::sync::atomic::{AtomicPtr, Ordering};
use std::sync::Arc;
use std::thread;
use std::time::Duration;

// 定义硬件状态结构体,实现Clone以便读取线程复制状态
#[derive(Clone, Debug)]
struct HardwareState {
    temperature: u32,
    voltage: f32,
    // 按需添加其他状态字段
}

impl Default for HardwareState {
    fn default() -> Self {
        Self {
            temperature: 0,
            voltage: 0.0,
        }
    }
}

fn main() {
    // 初始化初始状态,分配到堆上
    let initial_state = Box::new(HardwareState::default());
    let state_ptr = Arc::new(AtomicPtr::new(Box::into_raw(initial_state)));

    // 实时线程:模拟硬件交互并更新状态
    let rt_state_ptr = Arc::clone(&state_ptr);
    thread::spawn(move || {
        loop {
            // 模拟从硬件读取最新数据,生成新状态
            let new_state = Box::new(HardwareState {
                temperature: rand::random(),
                voltage: rand::random(),
            });
            // 原子替换指针,无阻塞完成写入
            let old_ptr = rt_state_ptr.swap(Box::into_raw(new_state), Ordering::Release);
            // 释放旧状态的堆内存,避免泄漏
            unsafe { Box::from_raw(old_ptr); }
            // 模拟实时线程的固定时序间隔
            thread::sleep(Duration::from_millis(10));
        }
    });

    // Web服务器线程:模拟API查询获取状态
    let web_state_ptr = Arc::clone(&state_ptr);
    thread::spawn(move || {
        loop {
            // 原子加载最新状态的指针
            let ptr = web_state_ptr.load(Ordering::Acquire);
            // 安全克隆当前状态,避免指针悬空风险
            let current_state = unsafe { (*ptr).clone() };
            println!("当前硬件状态: {:?}", current_state);
            // 模拟Web请求的间隔
            thread::sleep(Duration::from_secs(1));
        }
    });

    // 主线程保持运行
    thread::park();
}

核心优势

  • 实时线程的写入操作仅做原子指针交换,完全无阻塞,不会被读取线程的操作打断时序。
  • 读取线程通过克隆状态避免持有指针期间的竞争,不影响写入线程。
  • 内存顺序使用Release/Acquire保证状态可见性,性能优于强顺序的SeqCst。

方案2:AtomicCell(来自crossbeam-utils)- 适配Copy类型的状态

如果硬件状态是Copy类型(比如基础类型或简单结构体),使用crossbeam-utils提供的AtomicCell更简洁,无需手动管理内存,天然支持无锁读写。

代码示例

use crossbeam_utils::atomic::AtomicCell;
use std::sync::Arc;
use std::thread;
use std::time::Duration;

// 硬件状态实现Copy和Clone,适配AtomicCell
#[derive(Copy, Clone, Debug)]
struct HardwareState {
    temperature: u32,
    voltage: u32,
}

impl Default for HardwareState {
    fn default() -> Self {
        Self {
            temperature: 0,
            voltage: 0,
        }
    }
}

fn main() {
    let state = Arc::new(AtomicCell::new(HardwareState::default()));

    // 实时线程:更新状态
    let rt_state = Arc::clone(&state);
    thread::spawn(move || {
        loop {
            let new_state = HardwareState {
                temperature: rand::random(),
                voltage: rand::random(),
            };
            // 无阻塞写入新状态
            rt_state.store(new_state);
            thread::sleep(Duration::from_millis(10));
        }
    });

    // Web线程:读取最新状态
    let web_state = Arc::clone(&state);
    thread::spawn(move || {
        loop {
            // 获取最新状态
            let current_state = web_state.load();
            println!("当前硬件状态: {:?}", current_state);
            thread::sleep(Duration::from_secs(1));
        }
    });

    thread::park();
}

核心优势

  • API简洁,无需手动处理堆内存和指针转换,内存安全由AtomicCell保证。
  • store和load均为无锁原子操作,实时线程写入完全无阻塞。
  • 支持多读者同时读取,不会产生任何阻塞。

对比你之前的方案

  • 优于RwLock:写入线程无需等待读者,彻底避免阻塞风险。
  • 优于双缓冲:无需处理Rust借用检查器的可变引用问题,原子操作天然支持跨线程安全访问。
  • 优于mpsc:仅保留最新状态,不会因无Web请求导致内存堆积。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 00:45:15