C++

C++ std::mutex/

By using the Mutex keyword, we may lock our variable from being accessed by several threads at once. Mutex is utilized to provide synchronization in C++, meaning only one thread can receive the object at once.  Threads cannot access the locked piece of code once the lock has been established. The code has been locked using mutexes. So, even if thread 2 is scheduled while thread 1 is still consuming the shared resource, thread 2 will not be able to access that part of the code. As a result, synchronized access to shared resources in the code is ensured.

Working of Mutex in C++

Consider a situation in which one thread is running a section of code that a mutex has locked. Now, if the scheduler decides to change the context, all the other threads prepared to execute the same zone are unblocked. Only one thread out of all the others would be able to achieve this but if this thread attempted to execute a locked portion of code, it would again go to sleep.

There will be repeated context switches but until the mutex lock over the locked section of code is freed, no thread will be able to execute it. A thread that locked a mutex cannot release it.

Therefore, this makes sure that once a thread locks a portion of the code, no other thread can execute that region until the locked thread unlocks it.

So, while functioning on shared resources, this system makes sure that the threads are synchronized.

By invoking the two following functions, a mutex is initialized and a lock is then achieved: The first method initializes a mutex and the second function enables the locking of any crucial section of code.

# Int pthread_mutex_init(pthread_mutex_trylock *restrict mutex, const pthread_mutexattribute_trylock *restrict attribute):
Provides a mutex with the characteristics defined by the attribute and a reference to another mutex. The default mutex property (NONRECURSIVE) is utilized if the attribute is NULL. If pthread mutex init() is successful, it returns 0 and initializes and unlocks the mutex’s state. Pthread mutex init() returns -1 if it is unsuccessful.

# int pthread_mutex_lock(pthread_mutex_trylock *mutex) :
Classifies a mutex and locks a mutex object. The existing thread should wait for the mutex to unlock if it has previously been locked by another thread. A mutex is locked by the thread that locked it and that thread continues to be the mutex’s owner until that thread unlocks it. The way a lock is used can vary depending on whether the mutex has the recursive characteristic or not. When the same thread locks the same type of mutex more than once, the count is increased and no waiting thread is created.

To decrease the count to zero, the owning thread must make an equal number of calls to pthread_mutex_unlock().If successful, the Pthread_mutex_lock() function returns 0. Pthread_mutex_lock() returns -1 if it fails.

By carrying out the two actions indicated below, the mutex can be unlocked and destroyed. The lock can be opened using the first technique and it can also be destroyed so that it cannot be used in the future.

# int pthread_mutex_unlock(pthread_mutex_trylock *mutex) :
The mutex object is released. If several or more threads are queuing to block the mutex, pthread mutex unlock() compels one of the threads to do so. It also forces it to escape from pthread mutex lock() with the object mutex it had received previously. The mutex unlocks unless no threads are awaiting and it has no owner at the moment. The use of the lock may change if the mutex has the recursive characteristic.

When the same thread locks a given mutex more than once, the count is decreased upon unlock and no waiting thread is created to maintain the lock. The mutex is removed and any waiting threads are posted if the count is down to zero. Pthread_mutex_unlock() returns 0 if successful. Pthread_mutex_unlock() returns -1 in the event of failure.

int pthread_mutex_destroy(pthread_mutex_trylock *mutex) : removes a mutex object. Sometimes it is referred to as a mutex identifier from the system. Mutexes are utilized to safeguard shared resources. The mutex is initialized with an erroneous value yet pthread mutex init allows for re-initialization (). The successful return value of pthread_mutex_destroy() is 0. Pthread_mutex_destroy() returns -1 in the event of failure.

Example of Mutex in C++

An illustration of how thread synchronization is accomplished with mutexes.

Here, we have first given the thread id size “3”. Next, we have initialized the variable counter that records the frequency with the threads that are run. Then, we created the object lock for the pthread_mutex_lock. After that, we established a function “Mutex_func” where we have taken the lock reference and initialized the variable “m” with zero. The incremental value is entered into the counter variable.

Now, we have defined the main function of this script. The two variables are declared, one for mutex as “m” and one for the failure of mutex as “error”. When the “Mutex func()” method uses the shared resource “counter,” the same mutex is locked. The identical mutex is unlocked after the function “Mutex_func()”. The mutex is deleted once both threads have completed the main function. Note that only two tasks are performed respectively.

In the output, you can notice that one thread has started. Once the running thread is not destroyed the other task that has not started is the task. Therefore, both of the jobs begin and end logs are present this time. Thus, the use of Mutex enabled thread synchronization.

Conclusion

We can lock the object that contains the essential functionality of our application by using a mutex. Additionally, this avoids inconsistent data, which is crucial for real-time applications. Like how synchronization is implemented in other programming languages, mutex is employed. We have incorporated an example to explain the concept of std::mutex in the C++ programming language as well.

About the author

Omar Farooq

Hello Readers, I am Omar and I have been writing technical articles from last decade. You can check out my writing pieces.