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

Rust中如何跨Tokio多线程安全共享更新可变u32数值

Tokio多任务共享可变自增u32的实现方案

你之前推测更新数值需要配合await是错的,这个场景最优选择是std::sync::Arc<std::sync::atomic::AtomicU32>,全程无锁、不需要任何异步等待操作,性能拉满还完全线程安全。

  • 选型逻辑:
    • AtomicU32是标准库提供的原子类型,基于CPU硬件级原子指令实现,fetch_add(自增)、load(读值)操作都是同步完成的,执行时间只有纳秒级,不会阻塞Tokio的异步工作线程,根本不需要await。
    • Arc是原子引用计数指针,负责把计数器的所有权安全共享给多个spawn出来的Tokio任务,每个任务只需要clone一份Arc指针就能访问同一个底层计数器。
  • 最小可运行示例:
use std::sync::{
    atomic::{AtomicU32, Ordering},
    Arc,
};

#[tokio::main]
async fn main() {
    // 初始化初始值为0的计数器
    let counter = Arc::new(AtomicU32::new(0));
    let mut task_handles = Vec::new();

    // 启动10个任务操作同一个计数器
    for _ in 0..10 {
        let counter = counter.clone();
        task_handles.push(tokio::spawn(async move {
            // 安全自增1,返回自增前的值
            let old_val = counter.fetch_add(1, Ordering::SeqCst);
            // 读取当前最新值
            let current_val = counter.load(Ordering::SeqCst);
            println!("自增前值: {}, 自增后值: {}", old_val, current_val);
        }));
    }

    // 等待所有任务执行完成
    for handle in task_handles {
        handle.await.unwrap();
    }

    println!("最终计数结果: {}", counter.load(Ordering::SeqCst));
}
  • 注意事项:
    • 内存序没有特殊性能需求直接用Ordering::SeqCst就行,逻辑绝对安全,不会出现跨线程值不可见的问题;如果要做极致性能优化再根据场景调整内存序,新手别上来就用Relaxed,很容易踩可见性bug。
    • 绝对不要在这个场景用tokio::sync::Mutex,这个锁是专门给「持有锁期间需要执行await异步操作」的场景设计的,用在这种纳秒级的简单操作上纯纯增加不必要的开销。
    • 也没必要用std::sync::Mutex<u32>,虽然功能上能跑,但互斥锁的开销比原子操作高几个量级,属于杀鸡用牛刀。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 02:12:32