Search⌘ K
AI Features

Copied Value

Explore the copied value pattern in concurrency to prevent race conditions by passing thread data as a copy rather than a reference. Understand how this technique eliminates data races and lifetime issues in multithreaded C++ programs, enhancing safe parallel execution.

We'll cover the following...

In parallel programming, we can come across situations where different threads need the same resource. This can result in a race condition as the two threads compete for the same resource. To avoid consistency issues, we need to synchronize it. This problem can be solved using OS concepts like mutex locks, but those are not covered in the scope of this course. In this lesson, we’ll learn how the copied value pattern can solve our synchronization problem.

According to the copy value pattern, the thread should receive its data by copy and not by reference.

Let’s take a look at its code.

C++
// copiedValueDataRace.cpp
#include <functional>
#include <iostream>
#include <string>
#include <thread>
using namespace std::chrono_literals;
void byCopy(bool b){
std::this_thread::sleep_for(1ms);
std::cout << "byCopy: " << b << '\n';
}
void byReference(bool& b){
std::this_thread::sleep_for(1ms);
std::cout << "byReference: " << b << '\n';
}
void byConstReference(const bool& b){
std::this_thread::sleep_for(1ms);
std::cout << "byConstReference: " << b << '\n';
}
int main(){
std::cout << std::boolalpha << '\n';
bool shared{false};
std::thread t1(byCopy, shared);
std::thread t2(byReference, std::ref(shared));
std::thread t3(byConstReference, std::cref(shared));
shared = true;
t1.join();
t2.join();
t3.join();
std::cout << '\n';
}

Explanation

  • Line 29: We initialized a variable shared, which will be shared across the threads.

  • Lines 31–33: We created three threads:

    • t1: This calls the byCopy function with shared as the argument. This will pass the copy of the shared variable to the function.
    • t2: This calls the byReference function and will pass the shared variable through reference.
    • t3: This calls the byConstReference function with the constant reference of the shared variable.
  • Line 35: The value of the shared variable shared is changed to true.

  • Lines 37–39: We used join, due to which the main thread waits for other child threads to finish execution.

Each time we click the “Run” button, we should see different outputs due to race-condition among the threads, which causes data inconsistencies.

Advantage

  • Using the copied value makes it possible to eliminate data races and lifetime problems.