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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM