VOOZH about

URL: https://www.geeksforgeeks.org/cpp/data-races-in-cpp/

⇱ Data Races in C++ - GeeksforGeeks


  • Courses
  • Tutorials
  • Interview Prep

Data Races in C++

Last Updated : 23 Jul, 2025

In C++, data race is a commonly occurring problem in concurrent programming. It occurs when two or more threads concurrently access the same memory location, and at least one of the accesses is a write. Data races lead to undefined behaviour, which means the program can exhibit unpredictable behavior, crash, or produce incorrect results. Preventing data races is crucial for writing safe and reliable concurrent programs.

In this article we will discuss what are data races, what are its causes and how we can prevent them from happening in our program.

What Causes Data Race in C++?

There are many possible causes of the data races on C++. It can occur due to the concurrent execution of threads without proper synchronization. In a multi-threaded environment, if threads do not coordinate their access to shared data, it can result in:

  • Inconsistent Data: Different threads might read different values from the same variable.
  • Corrupted Data: One thread might overwrite the data being used by another thread.

Example of Data Race in C++

The following program demonstrate the data race condition in a concurrent program:

Output 1

Counter value: 146377

Output 2

Counter value: 200000

As seen from the above program, we may get different value in every execution. This is due to the data race condition.

How to Avoid Data Race in C++?

We can prevent the data races from happening by synchronizing the thread using various synchronizing primitives available in C++. Some of the are as follows:

  1. Mutex
  2. Atomic Operations
  3. Condition Variable

1. Preventing Data Race using Mutexes

A std::mutex can be used to ensure mutual exclusion, meaning that only one thread can access the critical section (shared data) of code at a time. Locking a mutex before accessing shared data ensures that only one thread can access the data at a time. We can unlock it when we are done working on it.

Syntax

std::mutex name // creating mutex

// In the callable
lock_guard<mutex> lock_name(name) // locking mutex

The mutex locked using lock_guard does not need to be explicitly unlocked at the end. They automatically gets unlocked when lock goes out of scope.

Example:


Output

Counter: 200000

To know more about mutex in C++, refer to the article - Mutex in C++

2. Atomic Operations

In C++, std::atomic provides atomic operations on fundamental data types, which means these operations are performed as a single, indivisible step. Atomic operations prevent data races without the need for explicit locks.

Syntax

std::atomic <type> var_name;

Example


Output

Counter: 200000

To know more about C++ Atomics, refer to the article - C++ 11 - <atomic> Header

3. Condition Variables

Condition variables are used to block a thread until a particular condition is met. They are used in conjunction with a mutex to wait for or signal changes in shared data.

Syntax

condition_variable name;

Example:


Output

Start Waiting
Notification Sent from the other thread
Resuming the work after notification

To know more about condition variable, refer to the article - Condition Variables in C++ Multithreading

Related Articles:


Comment