Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why we keep mutex instead of declaring it before guard every time?

Please consider this classical approach, I have simplified it to highlight the exact question:

#include <iostream>
#include <mutex>
using namespace std;

class Test
{
    public:
        void modify()
        {
            std::lock_guard<std::mutex> guard(m_);
            // modify data
        }
    private:
    /// some private data
    std::mutex m_;
};

This is the classical approach of using std::mutex to avoid data races.

The question is why are we keeping an extra std::mutex in our class? Why can't we declare it every time before the declaration of std::lock_guard like this?

void modify()
{
    std::mutex m_;
    std::lock_guard<std::mutex> guard(m_);
   // modify data
 }
like image 483
Eduard Rostomyan Avatar asked Mar 09 '18 10:03

Eduard Rostomyan


People also ask

Why do we need a mutex in C++?

They key to understanding the need for a mutex lies in the reordering of memory access and that lack atomicity in large data structures. The typical mutex solves both of these problems. It ensures that only one thread is executing a key piece of code at a time, which in turns limits access to a data structure.

What happens when a mutex is locked multiple times?

If no threads are waiting for the mutex, the mutex unlocks with no current owner. When the mutex has the attribute of recursive the use of the lock may be different. When this kind of mutex is locked multiple times by the same thread, then unlock will decrement the count and no waiting thread is posted to continue running with the lock.

Why does mutex unlock with no current owner?

If no threads are waiting for the mutex, the mutex unlocks with no current owner. When the mutex has the attribute of recursive the use of the lock may be different.

How many tasks can acquire a mutex?

Only one task (can be a thread or process based on OS abstraction) can acquire the mutex. It means there is ownership associated with a mutex, and only the owner can release the lock (mutex).


3 Answers

Lets say two threads are calling modify in parallel. So each thread gets its own, new mutex. So the guard has no effect as each guard is locking a different mutex. The resource you are trying to protect from race-conditions will be exposed.

like image 52
Naveen Avatar answered Nov 07 '22 10:11

Naveen


The misunderstanding comes from what the mutex is and what the lock_guard is good for.

A mutex is an object that is shared among different threads, and each thread can lock and release the mutex. That's how synchronization among different threads works. So you can work with m_.lock() and m_.unlock() as well, yet you have to be very careful that all code paths (including exceptional exits) in your function actually unlocks the mutex.

To avoid the pitfall of missing unlocks, a lock_guard is a wrapper object which locks the mutex at wrapper object creation and unlocks it at wrapper object destruction. Since the wrapper object is an object with automatic storage duration, you will never miss an unlock - that's why.

A local mutex does not make sense, as it would be local and not a shared ressource. A local lock_guard perfectly makes sense, as the autmoatic storage duration prevents missing locks / unlocks.

Hope it helps.

like image 25
Stephan Lechner Avatar answered Nov 07 '22 11:11

Stephan Lechner


This all depends on the context of what you want to prevent from being executed in parallel.

A mutex will work when multiple threads try to access the same mutex object. So when 2 threads try to access and acquire the lock of a mutex object, only one of them will succeed.

Now in your second example, if two threads call modify(), each thread will have its own instance of that mutex, so nothing will stop them from running that function in parallel as if there's no mutex.

So to answer your question: It depends on the context. The mission of the design is to ensure that all threads that should not be executed in parallel will hit the same mutex object at the critical part.

like image 36
The Quantum Physicist Avatar answered Nov 07 '22 11:11

The Quantum Physicist