What are the lifetimes of while loop arguments using a mutex?

Viewed 185

I was working through Rust's rustlings exercises and came up with a solution for threads1.rs shown below:

struct JobStatus {
    jobs_completed: u32,
}

fn main() {
    let status = Arc::new(Mutex::new(JobStatus { jobs_completed: 0 }));
    let status_shared = status.clone();
    thread::spawn(move || {
        for _ in 0..10 {
            thread::sleep(Duration::from_millis(250));
            status_shared.lock().unwrap().jobs_completed += 1;
        }
    });

    // WHILE LOOP IN QUESTION //
    while status.lock().unwrap().jobs_completed < 10 {
        println!("waiting... ");
        thread::sleep(Duration::from_millis(500));
    }
}

The solution above works perfectly and gives the desired results (i.e. the main thread only has to wait 6 times for the spawned thread to finish up 10 iterations).

However, according to the documentation for Rust, a lock for a Mutex is only released when the particular lock goes out of scope. But I do not understand why the lock created in the while loop was not held throughout the entire iteration and thereby making the main thread wait 10+ times. Is it because jobs_completed is a fixed size variable and is copied onto the stack when we borrow the value and thereby immediately releasing the lock? Or is there some other reason the while loop releases the lock immediately?

1 Answers

Is it because jobs_completed is a fixed size variable and is copied onto the stack when we borrow the value and thereby immediately releasing the lock?

The lock is getting released because the lock guard is only used for the time it takes to access jobs_completed, so the lock is only held for the span of the while's condition.

If by "fixed size variable" you mean Sized then... no. That jobs_completed is Copy makes things simpler, but even if it were not the lock would still only need to be held for the span of the loop condition, so without holding it explicitly it still would not be held for the entire loop.

Related