In this article we will discuss how to use mutex locks to protect shared data in multithreaded environment and avoid race conditions.

To fix race conditions in multi-threaded environment we need mutex i.e. each thread needs to lock a mutex before modifying or reading the shared data and after modifying the data each thread should unlock the mutex.

In the C++11 threading library, the mutexes are in the <mutex> header file. The class representing a mutex is the std::mutex class.

There are two important methods of mutex:
1.) lock()
2.) unlock()

We have explained Race condition using a Multithreaded Wallet in previous article i.e.

http://thispointer.com/c11-multithreading-part-4-data-sharing-and-race-conditions/

In this article we will see how to use mutex to fix the race condition in that multithreaded wallet.

As, Wallet provides a service to add money in Wallet and same Waqllet object is used between different threads, so we need to add Lock in addMoney() method of the Wallet i.e.
Acquire lock before incrementing the money of Wallet and release lock before leaving that function. Let’s see the code,

Wallet class that internally maintains money and provides a service/function i.e. addMoney().
This member function, first acquires a lock then increments the internal money of wallet object by specified count and then releases the lock.

Now Let’s create 5 threads and all these threads will share a same object of class Wallet and add 1000 to internal money using it’s addMoney() member function in parallel.

So, if initially money in wallet is 0. Then after completion of all thread’s execution money in Wallet should be 5000.

And this mutex lock guarantees that Money in the Wallet will be 5000 at end.

Let’s test this,

It’s guaranteed that it will not found a single scenario where money in wallet is less than 5000.
Because mutex lock in addMoney makes sure that once one thread finishes the modification of money then only any other thread modifies the money in Wallet.

But what if we forgot to unlock the mutex at the end of function. In such scenario, one thread will exit without releasing the lock and other threads will remain in waiting.
This kind of scenario can happen in case some exception came after locking the mutex. To avoid such scenarios we should use std::lock_guard.

std::lock_guard :

std::lock_guard is a class template, which implements the RAII for mutex.
It wraps the mutex inside it’s object and locks the attached mutex in its constructor. When it’s destructor is called it releases the mutex.

Let’s see the code,

Thanks.

Other C++11 Multi-threading Tutorials,

C++11 Multi-threading Part 1: Three Ways to Create Threads

C++11 Multi-threading Part 2: Joining and Detaching Threads

C++11 Multi-threading Part 3: Passing Arguments to Threads

C++11 Multi-threading Part 4: Sharing Data & Race Conditions

C++11 Multi-threading Part 5: Fixing Race Conditions using mutex

C++11 Multi-threading Part 6: Need of Event Handling

C++11 Multi-threading Part 7: Using Condition Variables to do Event Handling between threads

C++11 Multi-threading Part 8: std::future and std::promise

C++11 Multithreading – Part 9: std::async Tutorial & Example

 

 

Click Here to Subscribe for more Articles / Tutorials like this.