简体   繁体   中英

What are the semantics of move in rust?

use std::sync::{Arc, Mutex};
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);
        let handle = thread::spawn(move || {
            let mut num = counter.lock().unwrap();
            *num += 1;
            println!("Inner counter: {}", Arc::strong_count(&counter));
        });
        handles.push(handle);

        // println!("Inter counter: {}", Arc::strong_count(&counter));
    }

    println!("Outer counter: {}", Arc::strong_count(&counter));

    for handle in handles {
        handle.join().unwrap();
    }

    println!(
        "Result: {}, {}",
        *counter.lock().unwrap(),
        Arc::strong_count(&counter)
    );
}

Why can Inner counter and Outer counter output, but Inter counter will report an error?

If I uncomment Inter counter , the rust compiler tells me:

let counter: Arc<Mutex<i32>>
Go to Arc | Mutex

borrow of moved value: `counter`
value borrowed here after moverustcE0382
main.rs(10, 36): value moved into closure here
main.rs(11, 27): variable moved due to use in closure
main.rs(9, 13): move occurs because `counter` has type `Arc<Mutex<i32>>`, which does not implement the `Copy` trait

If counter has been moved inside the closure at theread::apawn , why can the outside still use it?

I'm not sure whether this is caused by the move keywords.

If counter has been moved inside the closure at theread::apawn, why can the outside still use it?

Because you have two completely different variables with the name counter :

    let counter = Arc::new(Mutex::new(0));

and

        let counter = Arc::clone(&counter);

The second one gets move -d inside the closure, but the first one only gets borrowed during the iteration in order to clone it.

When the second counter gets created, it shadows the first one for the rest of the loop's body. So your code is semantically the same as:

    for _ in 0..10 {
        let counter2 = Arc::clone(&counter);
        let handle = thread::spawn(move || {
            let mut num = counter2.lock().unwrap();
            *num += 1;
            println!("Inner counter: {}", Arc::strong_count(&counter2));
        });
        handles.push(handle);

        println!("Inter counter: {}", Arc::strong_count(&counter2));
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM