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

Rust线程任务分配不均问题的原因排查与解决

Rust线程任务分配不均问题排查

我正在学习Rust,写了一段多线程代码,发现其中一个线程执行次数远多于另一个,任务分配不均。相同逻辑的C++代码运行正常,求找出Rust代码中的问题。

原代码

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

struct Client {
    id: i32,
}

impl fmt::Display for Client {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        writeln!(f, "Client id: {:?}", self.id)
    }
}

fn main() {
    let client: Client = Client { id: 0 };
    let counter = Arc::new(Mutex::new(client));
    let mut handles = vec![];

    // 线程1
    let safe_client_1 = Arc::clone(&counter);
    let thread_1 = thread::spawn(move || loop {
        let mut num = safe_client_1.lock().unwrap();
        num.id += 1;
        print!("thread 1: {}", num);
        thread::sleep(Duration::from_secs(1));
    });
    handles.push(thread_1);

    // 线程2
    let safe_client_2 = Arc::clone(&counter);
    let thread_2 = thread::spawn(move || loop {
        let mut num = safe_client_2.lock().unwrap();
        num.id -= 1;
        print!("thread 2: {}", num);
        thread::sleep(Duration::from_secs(1));
    });

    loop {}
}

原输出

thread 1: Client id: 1
thread 1: Client id: 2
thread 2: Client id: 1
thread 2: Client id: 0
thread 2: Client id: -1
thread 2: Client id: -2
thread 2: Client id: -3
thread 2: Client id: -4
thread 2: Client id: -5
thread 2: Client id: -6
thread 2: Client id: -7
thread 1: Client id: -6
thread 2: Client id: -7
thread 2: Client id: -8
thread 2: Client id: -9
thread 2: Client id: -10
thread 2: Client id: -11
thread 2: Client id: -12
thread 2: Client id: -13
thread 2: Client id: -14
thread 2: Client id: -15
thread 2: Client id: -16
thread 2: Client id: -17
thread 2: Client id: -18
thread 2: Client id: -19
thread 2: Client id: -20
thread 2: Client id: -21
thread 2: Client id: -22
thread 2: Client id: -23
thread 2: Client id: -24
thread 2: Client id: -25
thread 2: Client id: -26
thread 2: Client id: -27

问题原因

核心问题在于MutexGuard的生命周期管理。原代码中,num作为MutexGuard变量,其生命周期覆盖了整个loop迭代,包括thread::sleep的1秒时间。这意味着线程在休眠时仍然持有互斥锁,另一个线程完全无法获取锁,只能等待当前线程的loop迭代结束、num被销毁后才能抢到锁。这种设计导致了一个线程长时间占据锁,另一个线程只有极小的概率在锁释放瞬间抢到执行权,最终出现任务分配极度不均的现象。

解决代码

通过手动调用drop(num)提前释放MutexGuard,确保在休眠前就释放锁,让另一个线程有机会获取锁并执行任务:

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

struct Client {
    id: i32,
}

impl fmt::Display for Client {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        writeln!(f, "Client id: {:?}", self.id)
    }
}

fn main() {
    let client: Client = Client { id: 0 };
    let counter = Arc::new(Mutex::new(client));

    // 线程1
    let safe_client_1 = Arc::clone(&counter);
    let thread_1 = thread::spawn(move || loop {
        let mut num = safe_client_1.lock().unwrap();
        num.id += 1;
        print!("thread 1: {}", num);
        drop(num); // 提前释放锁
        thread::sleep(Duration::from_secs(1));
    });

    // 线程2
    let safe_client_2 = Arc::clone(&counter);
    let thread_2 = thread::spawn(move || loop {
        let mut num = safe_client_2.lock().unwrap();
        num.id -= 1;
        print!("thread 2: {}", num);
        drop(num); // 提前释放锁
        thread::sleep(Duration::from_secs(1));
    });

    loop {}
}

解决后输出

thread 1: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0
thread 1: Client id: 1
thread 2: Client id: 0
thread 1: Client id: 1
thread 2: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0
thread 1: Client id: 1
thread 2: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0
thread 1: Client id: 1
thread 2: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0
thread 1: Client id: 1
thread 2: Client id: 0
thread 1: Client id: 1
thread 2: Client id: 0
thread 1: Client id: 1
thread 2: Client id: 0
thread 1: Client id: 1
thread 2: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0
thread 1: Client id: 1
thread 2: Client id: 0
thread 1: Client id: 1
thread 2: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0
thread 1: Client id: 1
thread 2: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0
thread 1: Client id: 1
thread 2: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0
thread 1: Client id: 1
thread 2: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0
thread 1: Client id: 1
thread 2: Client id: 0
thread 2: Client id: -1
thread 1: Client id: 0

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 20:25:18