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

Rust使用Rayon多线程修改共享变量(可接受竞态条件)如何实现?

问题原因

Rayon 并行迭代器的for_each方法要求传入的闭包实现Fn trait,即闭包可以被多个线程同时安全调用。你原代码中的闭包捕获了栈上可变变量i的独占引用,只能实现FnMut trait,仅支持单线程依次调用,不满足多线程并行调用的约束,因此编译失败。

实现方案

方案1:允许数据竞争(含未定义行为,仅做演示)

如果你明确不需要规避数据竞争、接受未定义行为的后果,可以通过unsafe + UnsafeCell绕过编译器检查:

use rayon::prelude::*;
use std::cell::UnsafeCell;
use std::sync::Arc;

fn main() {
    // UnsafeCell 允许内部可变性,配合Arc满足多线程共享生命周期要求
    let i = Arc::new(UnsafeCell::new(0));
    let closure = move |_| {
        unsafe {
            // 直接通过裸指针修改,此处会产生数据竞争,属于未定义行为
            *i.get() = *i.get() + 1;
        }
    };

    (0..100).into_par_iter().for_each(closure);
    unsafe {
        // 输出结果大概率小于100,极端情况下可能出现异常值
        println!("最终i的值: {}", *i.get());
    }
}

警告:该代码包含未定义行为,绝对禁止在生产环境使用。

方案2:无未定义行为,仅允许计数丢失

如果你只是接受最终计数结果不准确、不需要强一致性,可以使用宽松内存序的原子变量,既满足多线程修改要求,又不会触发未定义行为:

use rayon::prelude::*;
use std::sync::atomic::{AtomicUsize, Ordering};

fn main() {
    let i = AtomicUsize::new(0);
    let closure = |_| {
        // Relaxed内存序仅保证操作原子性,无同步开销,允许计数丢失
        i.fetch_add(1, Ordering::Relaxed);
    };

    (0..100).into_par_iter().for_each(closure);
    println!("最终i的值: {}", i.load(Ordering::Relaxed));
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 09:36:04