zoukankan      html  css  js  c++  java
  • Rust学习 mutex

    use std::sync::Mutex;
    
    fn main() {
        let m = Mutex::new(5);  //Mutex<i32>, 智能指针
    
        {
            let mut num = m.lock().unwrap();  //等待,阻塞线程,
            //返回MutexGuard, 智能指针,实施deref and drop
            //如果其他线程锁定并惊慌,谁都得不到锁,所以直接unwrap
            *num = 6;  //num is &mut i32, deref
        }
    
        println!("m = {:?}", m);
    }
    cargo run
        Finished dev [unoptimized + debuginfo] target(s) in 0.01s
         Running `target/debug/hello_world`
    m = Mutex { data: 6 }
    //进程共享mutex
    use std::sync::Mutex;
    use std::thread;
    
    fn main() {
        let counter = Mutex::new(0);
        let mut handles = vec![];
    
        for _ in 0..10 {
            let handle = thread::spawn(move || {
                let mut num = counter.lock().unwrap();  //错误,第一个线程搬走counter
    
                *num += 1;  //deref MutexGuard
            });
            handles.push(handle);
        }
    
        for handle in handles {
            handle.join().unwrap();
        }
    
        println!("Result: {}", *counter.lock().unwrap());  //deref MutexGuard
    }
    cargo build
       Compiling hello_world v0.1.0 (/data2/rust/mutex2)
    error[E0382]: use of moved value: `counter`
      --> src/main.rs:10:36
       |
    6  |     let counter = Mutex::new(0);
       |         ------- move occurs because `counter` has type `std::sync::Mutex<i32>`, which does not implement the `Copy` trait
    ...
    10 |         let handle = thread::spawn(move || {
       |                                    ^^^^^^^ value moved into closure here, in previous iteration of loop
    11 |             let mut num = counter.lock().unwrap();  //错误,第一个线程搬走counter
       |                           ------- use occurs due to use in closure
    
    error: aborting due to previous error
    
    For more information about this error, try `rustc --explain E0382`.
    error: could not compile `hello_world`.
    
    To learn more, run the command again with --verbose.
    //进程共享mutex
    use std::sync::Mutex;
    use std::thread;
    
    fn main() {
        let counter = Mutex::new(0);
        let mut handles = vec![];
    
            let handle = thread::spawn(move || {
                let mut num = counter.lock().unwrap();  //错误,第一个线程搬走counter
    
                *num += 1;  //deref MutexGuard
            });
            handles.push(handle);
    
        for handle in handles {
            handle.join().unwrap();
        }
    
        println!("Result: {}", *counter.lock().unwrap());  //deref MutexGuard
    }
     cargo build
       Compiling hello_world v0.1.0 (/data2/rust/mutex2)
    error[E0382]: borrow of moved value: `counter`
      --> src/main.rs:20:29
       |
    6  |     let counter = Mutex::new(0);
       |         ------- move occurs because `counter` has type `std::sync::Mutex<i32>`, which does not implement the `Copy` trait
    ...
    9  |         let handle = thread::spawn(move || {
       |                                    ------- value moved into closure here
    10 |             let mut num = counter.lock().unwrap();  //错误,第一个线程搬走counter
       |                           ------- variable moved due to use in closure
    ...
    20 |     println!("Result: {}", *counter.lock().unwrap());  //deref MutexGuard
       |                             ^^^^^^^ value borrowed here after move
    
    error: aborting due to previous error
    
    For more information about this error, try `rustc --explain E0382`.
    error: could not compile `hello_world`.
    //使用Rc<T>共享
    use std::rc::Rc;
    use std::sync::Mutex;
    use std::thread;
    
    fn main() {
        let counter = Rc::new(Mutex::new(0));
        let mut handles = vec![];
    
        for _ in 0..10 {
            let counter = Rc::clone(&counter);
            let handle = thread::spawn(move || {
                let mut num = counter.lock().unwrap();  //错误,Rc<T>不是线程安全
                //Rc<T>.lock -> Mutex<>.lock
    
                *num += 1;
            });
            handles.push(handle);
        }
    
        for handle in handles {
            handle.join().unwrap();
        }
    
        println!("Result: {}", *counter.lock().unwrap());
    }
     Compiling hello_world v0.1.0 (/data2/rust/mutex3)
    error[E0277]: `std::rc::Rc<std::sync::Mutex<i32>>` cannot be sent between threads safely
       --> src/main.rs:11:22
        |
    11  |           let handle = thread::spawn(move || {
        |  ______________________^^^^^^^^^^^^^_-
        | |                      |
        | |                      `std::rc::Rc<std::sync::Mutex<i32>>` cannot be sent between threads safely
    12  | |         let mut num = counter.lock().unwrap(); 
    13  | |         //错误,Rc<T>不是线程安全
    14  | |         //Rc<T>.lock -> Mutex<>.lock
    15  | |
    16  | |             *num += 1;  //deref MutexGuard
    17  | |         });
        | |_________- within this `[closure@src/main.rs:11:36: 17:10 counter:std::rc::Rc<std::sync::Mutex<i32>>]`
        |
        = help: within `[closure@src/main.rs:11:36: 17:10 counter:std::rc::Rc<std::sync::Mutex<i32>>]`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<std::sync::Mutex<i32>>`
        = note: required because it appears within the type `[closure@src/main.rs:11:36: 17:10 counter:std::rc::Rc<std::sync::Mutex<i32>>]`
    
    error: aborting due to previous error
    
    For more information about this error, try `rustc --explain E0277`.
    error: could not compile `hello_world`.
    
    To learn more, run the command again with --verbose.
    [root@bogon mutex3]# 
    //使用Arc, Atomic Rc, 多线程版Rc,语法相同
    use std::sync::{Mutex, Arc};
    use std::thread;
    
    fn main() {
        let counter = Arc::new(Mutex::new(0));  
    
        let mut handles = vec![];
    
        for _ in 0..10 {
            let counter = Arc::clone(&counter);  //counter不可变
            let handle = thread::spawn(move || {
                let mut num = counter.lock().unwrap();
    
                *num += 1;  //可变,Mutex具有内部可变性,类似RefCell
                //同时,Mutex也可能造成死锁,类似Rc的引用循环
            });
            handles.push(handle);
        }
    
        for handle in handles {
            handle.join().unwrap();
        }
    
        println!("Result: {}", *counter.lock().unwrap());
    }
    
    //实施了std::marker下的send的类型叫做send, 实施了sync的叫做sync
    //send可以在线程间转移所有权,sync引用可以被线程共享,T是sync, 则&T is send
    //大部分类型是send and sync
    //Rc<T>, RefCell<T>, Cell<T>不是send也不是sync, 
    //Mutex是sync, 所以引用可以被线程共享
    Result: 10
  • 相关阅读:
    webpack进阶(二)
    webpack的loader和plugin的区别
    接口和面向接口编程
    设计原则与编程技巧汇总
    W3C的盒子模型和IE的盒子模型
    React的组件
    React的路由react-router
    三种编程命名规则:驼峰命名法,帕斯卡命名法,匈牙利命名法
    gulp 构建 demo
    antd 表单的两种校验方式
  • 原文地址:https://www.cnblogs.com/dream397/p/14200612.html
Copyright © 2011-2022 走看看