Implementing Race Condition in C++

Last Updated : 9 Jul, 2026

A race condition occurs when multiple threads access and modify shared data simultaneously without proper synchronization. Since the execution order depends on thread scheduling, the program may produce different outputs on different runs.

  • Race conditions occur due to unsynchronized concurrent access.
  • They often lead to inconsistent or unpredictable results.
C++
#include <iostream>
#include <thread>
using namespace std;

int counter = 0;

void increment() {
    for (int i = 0; i < 100000; i++) {
        counter++;
    }
}

int main() {
    thread t1(increment);
    thread t2(increment);

    t1.join();
    t2.join();

    cout << counter;
}

Output
117325

Explanation: Both threads access and modify the same shared variable at the same time, causing some updates to overlap and get lost. As a result, the final value depends on the order in which the threads execute, so the output may vary across different runs.

Eliminating the Race Condition

A race condition can be prevented by protecting the critical section with a mutex, ensuring that only one thread accesses the shared resource at a time.

C++
#include <iostream>
#include <mutex>
#include <thread>
using namespace std;

int counter = 0;
mutex mtx;

void increment()
{
    for (int i = 0; i < 1000000; i++) {
        lock_guard<mutex> lock(mtx);
        counter++;
    }
}

int main()
{
    thread t1(increment);
    thread t2(increment);

    t1.join();
    t2.join();

    cout << "Counter = " << counter << endl;
    return 0;
}

Output
Counter = 2000000

Explanation: The mutex ensures that only one thread updates the shared counter at a time, preventing lost updates and producing a consistent output.

Causes of Race Conditions

Race conditions occur when multiple threads access shared data without proper synchronization, causing the program's result to depend on the order in which the threads execute.

  • Multiple threads access the same shared resource simultaneously.
  • At least one thread modifies the shared data.
  • Shared resources are accessed without proper synchronization (such as a mutex).
  • The execution order of threads is unpredictable, so different runs may produce different results.

Preventing Race Conditions

Race conditions can be avoided by ensuring that shared resources are accessed in a controlled and synchronized manner.

  • Protect critical sections using synchronization primitives such as mutexes.
  • Use atomic variables for simple shared read and write operations.
  • Minimize sharing of mutable data between multiple threads.
  • Ensure threads are properly synchronized before accessing shared resources.

Related article: Race Condition Vulnerability

Comment