Monday, July 29, 2024

C++ 20 multi threaded programming - the introduction of std::atomic...

Data races in C++ multithreaded applications occur when multiple threads try to access a single data without proper data locking tools like mutex.

Causes of Data Races

  1. Concurrent Reads and Writes: If one thread reads a variable while another writes to it without synchronization, a data race occurs.
  2. Concurrent Writes: If multiple threads write to the same variable concurrently without synchronization, it leads to a data race.
  3. Lack of Synchronization Primitives: Not using mutexes, atomic operations, or other synchronization mechanisms can result in data races.

Data race may cause unpredictable output and even crashes.

For example, look at the below C++ programs.

//============================================================================

// Name : C++20Atomic.cpp

// Author : Som

// Version :

// Copyright : som-itsolutions

// Description : Hello World in C++, Ansi-style

//============================================================================


#include <iostream>

#include <atomic>

#include <thread>


int counter = 0;



void incrementCounter() {

for (int i = 0; i < 10000; ++i) {

counter++;

}

}


int main() {

std::thread t1(incrementCounter);

std::thread t2(incrementCounter);


t1.join();

t2.join();


std::cout << "Final counter value: " << counter << std::endl;


return 0;

}

Here two threads are trying to access a single variable without a proper synchronization technique.

Here is the video in which the program is run in Eclipse.


You can see that as the counter increases, the output is incorrect. This is because we didn't use any thread-safe way to access the variable.

In C++ 20, with the introduction of atomic data, this can be easily handled.

So, now we have changed the simple variable into an atomic variable.

//============================================================================

// Name : C++20Atomic.cpp

// Author : Som

// Version :

// Copyright : som-itsolutions

// Description : Hello World in C++, Ansi-style

//============================================================================


#include <iostream>

#include <thread>

#include <atomic>


std::atomic<int> counter(0);


void incrementCounter() {

for (int i = 0; i < 10000000; ++i) {

counter++;

}

}


int main() {

std::thread t1(incrementCounter);

std::thread t2(incrementCounter);


t1.join();

t2.join();


std::cout << "Final counter value: " << counter << std::endl;


return 0;

}


And voila...

The output result is perfect...



C++ is gradually becoming powerful after a very long period of hibernation. 

Enjoy...

No comments: