跳到主内容
Rust
文章阅读

Rust中的Arc和Mutex互斥锁在线程中的使用

2025/12/1668 次阅读3 分钟


use std::thread;
use std::sync::Arc;
use std::sync::Mutex;


/**

Arc 代表原子引用计数,它是使用原子操作的RC的线程安全版本
Arc::clone 在执行原子操作方面有开销,但是在此之后,T可以随意使用,而且没有任何开销


注意在循环里面使用,Arc不会使用垃圾回收器检测引用循环

**/
fn main1() {
    let v = Arc::new(vec![10,20,30]);
    let mut handles = Vec::new();
    for _ in 1..5 {
        let v= Arc::clone(&v);
        handles.push(thread::spawn(move || {
            let thread_id = thread::current().id();
            println!("{thread_id:?}:{v:?}");
        }));
    }

    handles.into_iter().for_each(|h| h.join().unwrap());
    println!("v:{v:?}")
}



/**


互斥器

rust中的互斥器看起来就像是包含一个元素的集合,其中的元素就是受保护的数据

在访问受保护的数据之前,不可能忘记获取互斥量

你可以通过获取锁,从&Mutex<T>中获取&mut T ,MutexGuard 能够确保&mut T存在的时间不会比持有锁的时间更长

读写锁版本==>> RwLock

为什么lock会返回Result?

如果持有Mutex的线程发生panic ,Mutex便会中毒并发出信号,表明其所保护的数据可能处于不一致的状态
对中毒的互斥量调用lock()就会失败,并将显示PoisonError(poison:翻译过来就是毒药的意思)
无论如何,你可以对这个错误调用into_inner()来恢复数据

**/
fn main2(){

    let v = Mutex::new(vec![10,20,30]);
    println!("v:{:?}",v.lock().unwrap());
    {
        let mut guard = v.lock().unwrap();
        guard.push(40);
    }
    println!("v:{:?}",v.lock().unwrap());
}


// fn main3(){
//     let mut v = vec![10, 20, 30];
//     let handle = thread::spawn(||{
//         v.push(10);
//     });
//     v.push(1000);
//     handle.join().unwrap();
//     println!("v:{v:?}");
// }


///解决上面main3的问题
///
///
/// 注意:把Mutex封装在Arc里面是一种在线程之间共享可变状态的常见模式
/// v:Arc<_>必须先克隆为v2,让后才能移动到另一个线程中,注意:lambda签名中添加了move

fn main(){
    let v = Arc::new(Mutex::new(vec![10,20,30]));
    let v2 = Arc::clone(&v);
    let handle = thread::spawn(move||{
        let mut v2 = v2.lock().unwrap();
        v2.push(10);
    });
    {
        let mut v = v.lock().unwrap();
        v.push(1000);
    }
    handle.join().unwrap();
    println!("v:{v:?}");
}
返回顶部