Dropping Mutex Guards

Hi,

I'm using Mutexes to access a global configuration. Currently, I'm accessing the mutex like so:

let lock = mutex.lock();
let data = lock.field.clone();
drop(lock);

This is very verbose but ensures that I only hold the lock for the duration of the clone.

I was wondering whether this:

let data = mutex.lock().field.clone();

is equivalent?

I think it is because the guard isn't stored in a named variable and therefore should be dropped immediately. But, I have very little experience with Mutexes and would like to make sure.

1 Like

Temporaries live for the duration of the current statement. If you just need to hold the mutex long enough to call clone(), yes, the one-liner is equivalent. You can trust that if it were an improper use the compiler would reject it. It won't stop you from holding the guard for too long but it will definitely complain if you drop it too early.

5 Likes

Incidentally you can investigate things like this yourself by running this (e.g. using Tools > Miri in the playground), which deadlocks:

fn main() {
    let data = Data { field: String::new() };
    let mutex = Mutex::new(data);

    let lock = mutex.lock();
    let data = lock.field.clone();
    let lock = mutex.lock(); // <-- bad
    drop(lock);
 }

And comparing to this, which does not:

fn main() {
    let data = Data { field: String::new() };
    let mutex = Mutex::new(data);

    let data = mutex.lock().field.clone();
    let lock = mutex.lock(); // <-- ok
    drop(lock);
 }

Playground.

2 Likes