Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does a mutex unlock when it comes out of scope?

Simple question - basically, do I have to unlock a mutex, or can I simply use the scope operators and the mutex will unlock automatically?

ie:

{ 
    pthread_mutex_lock (&myMutex); 
    sharedResource++; 
} // my mutex is now unlocked?

or should I:

{ 
    pthread_mutex_lock (&myMutex); 
    sharedResource++;
    pthread_mutex_unlock (&myMutex);
}
like image 829
Amit Nayar Avatar asked Jul 18 '13 16:07

Amit Nayar


People also ask

How do you unlock a mutex?

The mutex does not become unlocked until the owner has called pthread_mutex_unlock() for each successful lock request that it has outstanding on the mutex. An errorcheck mutex checks for deadlock conditions that occur when a thread relocks an already held mutex.

What happens when mutex is locked?

Mutexes are used to protect shared resources. If the mutex is already locked by another thread, the thread waits for the mutex to become available. The thread that has locked a mutex becomes its current owner and remains the owner until the same thread has unlocked it.

Does Unique_lock automatically unlock?

The std::scoped_lock and std::unique_lock objects automate some aspects of locking, because they are capable of automatically unlocking.

How long does a mutex lock take?

Using std::mutex takes about 74 machine cycles, while using a native Win32 CRITICAL_SECTION takes about 53 machine cycles. So unless 100 machine cycles is a significant amount of time compared to the code itself, the mutexes aren't going to be the source of a performance problem.


2 Answers

The mutex is not going out of scope in your examples; and there is no way for the compiler to know that a particular function needs calling at the end of the scope, so the first example does not unlock the mutex.

If you are using (error-prone) functions to lock and unlock the mutex, then you will need to ensure that you always call unlock() - even if the protected operation throws an exception.

The best way to do this is to use a RAII class to manage the lock, as you would for any other resource that needs releasing after use:

class lock_guard {
public:
    explicit lock_guard(mutex & m) : m(m) {mutex_lock(m);}
    ~lock_guard() {mutex_unlock(m);}

    lock_guard(lock_guard const &) = delete;
    void operator=(lock_guard &) = delete;

private:
    mutex & m;
};

// Usage
{
    lock_guard lock(myMutex);
    shared_resource++;
} // mutex is unlocked here (even if an exception was thrown)

In modern C++, use std::lock_guard or std::unique_lock for this.

like image 113
Mike Seymour Avatar answered Sep 28 '22 22:09

Mike Seymour


Using the RAII scope method is much better because it guarantees that the mutex will always be unlocked even in the face of exceptions or early return.

If you have access to C++11 though you might consider using a std::atomic<int> instead in which case you don't need to lock it to increment.

like image 32
Mark B Avatar answered Sep 28 '22 22:09

Mark B