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

Rust中多线程固定位置写入同一数组的实现问题

解决多线程写入数组固定位置的问题

你的代码存在三个核心问题:

  1. 变量克隆错误:shared_j_copy错误克隆了shared_array,导致它的类型是Arc<Mutex<[i32;10]>>,而非你需要的Arc<Mutex<usize>>,直接引发后续类型不匹配错误。
  2. MutexGuard使用错误:调用lock()后得到的MutexGuard是智能指针,不能直接作为数组索引,也不能直接对它执行+=操作,必须解引用获取内部实际值。
  3. 锁的持有时机不合理:如果在持有锁的状态下执行耗时操作,会导致其他线程阻塞,完全失去并行执行的意义。

修正后的基础版本代码

先解决这些错误,让代码正常运行:

use std::thread;
use std::time::Duration;
use std::sync::{Arc, Mutex};

fn main(){
    let shared_array = Arc::new(Mutex::new([0;10]));
    let shared_j = Arc::new(Mutex::new(0 as usize));

    let mut handles = vec![];

    for _ in 0..10 {
        // 正确克隆对应的共享变量
        let array_clone = shared_array.clone();
        let j_clone = shared_j.clone();

        let handle = thread::spawn(move || {
            // 先获取并递增索引,立即释放锁
            let mut j_guard = j_clone.lock().unwrap();
            let index = *j_guard;
            *j_guard += 1;
            drop(j_guard); // 手动释放锁,避免持有锁执行耗时操作

            // 模拟耗时操作
            thread::sleep(Duration::from_millis(1000));

            // 写入数组对应位置
            let mut tab = array_clone.lock().unwrap();
            println!("写入 tab[{}]", index);
            tab[index] = index as i32;
        });

        handles.push(handle);
    }

    // 等待所有线程完成,替代sleep的不精确方式
    for handle in handles {
        handle.join().unwrap();
    }

    let tab = shared_array.lock().unwrap();
    println!("tab= {:?}", tab);
}

更优方案:直接分配固定索引

你完全不需要共享的索引变量,循环本身可以直接给每个线程分配固定的索引位置,既避免锁竞争,代码也更简洁:

use std::thread;
use std::time::Duration;
use std::sync::{Arc, Mutex};

fn main(){
    let shared_array = Arc::new(Mutex::new([0;10]));
    let mut handles = vec![];

    // 直接在循环中给每个线程分配固定索引
    for index in 0..10 {
        let array_clone = shared_array.clone();

        let handle = thread::spawn(move || {
            // 模拟你的400行耗时操作
            thread::sleep(Duration::from_millis(1000));

            // 写入对应位置
            let mut tab = array_clone.lock().unwrap();
            println!("写入 tab[{}]", index);
            tab[index] = index as i32;
        });

        handles.push(handle);
    }

    // 等待所有线程完成
    for handle in handles {
        handle.join().unwrap();
    }

    let tab = shared_array.lock().unwrap();
    println!("tab= {:?}", tab);
}

方案说明

  • 直接分配固定索引的方式彻底避免了锁竞争,性能更高。
  • 使用join()等待所有线程完成,比sleep()更可靠,不会因为耗时操作实际时间超过sleep时长导致结果未写入完成。
  • 耗时操作放在锁外面,只在写入数组的瞬间持有锁,最大程度保证并行效率。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 04:16:07