Mutex locks even in a single thread

Hello list,

Why are Mutexes preventing access from the same thread? Consider this:

use std::sync::Mutex;

fn main() {
    let mutex = Mutex::new(32);
    let guard = mutex.lock().unwrap();
    println!("Hello world");
    
    // uncomment lines below and this never terminates
    // let guard2 = mutex.lock().unwrap();
    // println!("Hello world 2");
}

I'm currently trying to build a mutable tree like so:

pub struct LmiNode<T> {
    children: [Option<Arc<Mutex<LmiNode<T>>>>; 10],
    pub value: Option<Arc<Mutex<T>>>
}

So I have to lock each child as I descend to the tree to fetch some value, but when I try to change the same value or maybe do a second lookup in the same scope in the same thread, my code hangs because of some Mutex already locked the value.

I thought the point of Mutexes was to prevent access from another thread, not the same thread!!! How would you go around this issue?

Kind Regards
JM

A mutex guard lets you obtain a &mut reference to the contents, which asserts that you have exclusive access. If you could lock it multiple times in one thread, it would not guarantee exclusive access, and thus it would not be valid for it to provide an &mut reference.

In short, the point of a mutex is to guarantee exclusive access.

4 Likes

For a single thread there's a way to access the mutex without locking it (the borrow checker will enforce the exclusivity rule):

2 Likes

What you want is called reentrant mutex. The parking_lot crate provides one. It allows you to share !Sync types between threads. But due to its aliasible nature it only gives you &T not &mut T. You can have ReentrantMutex<RefCell<T>> though.

3 Likes

Wow, thanks for this, this looks like what I need... I'm going to try that & let you know how it goes, thanks!

replying to myself here... the fact that I can't get &mut T is kind of a showstopper here... RefCell opens up a can of runtime panic worms...

And if I make everything immutable well... what's the point for mutex & locks then? :face_with_monocle:

The definition of an &mut T is that it provides exclusive access, so you can't have a reentrant mutex that gives an &mut T. If you don't like RefCell, maybe Cell is more useful to you?

I have an article that may illuminate what is going on:

3 Likes