DEV Community

Rondale Sidbury
Rondale Sidbury

Posted on

std::lock_guard

{
"response": "Here is the bug and how to fix it!\n\n### The Bug: Data Race\nThe bug is in counter.cpp inside the increment() method:\n

cpp\nvoid Counter::increment() {\n value++; // INTENTIONAL BUG\n}\n

\nThe value++ operation is not a single, indivisible step. It actually takes three steps at the CPU level:\n1. Read the current value from memory into a register.\n2. Increment the value in the register.\n3. Write the new value back to memory.\n\nWhen 100 threads do this at the exact same time, Thread A and Thread B might both read the value 50. Both increment it to 51, and both write 51 back to memory. Two increments happened, but the counter only went up by one. This results in the final count being much lower than expected.\n\n### The Fix\nThere are two standard ways to fix this in C++. For a simple counter, using std::atomic is the most efficient and cleanest approach. \n\n#### Solution 1: Using std::atomic (Recommended)\nstd::atomic guarantees that operations on the variable happen as a single, indivisible (atomic) operation. \n\n
Update counter.h:\n

cpp\n#ifndef COUNTER_H\n#define COUNTER_H\n#include <atomic> // Include atomic library\n\nclass Counter {\npublic:\n Counter();\n void increment();\n int getValue() const;\nprivate:\n std::atomic<int> value; // Change int to std::atomic<int>\n};\n\n#endif // COUNTER_H\n

\n\n
Update counter.cpp:\n(No changes needed!)* std::atomic overloads the ++ operator to be thread-safe automatically.\n

cpp\n#include \"counter.h\"\n\nCounter::Counter() : value(0) {}\n\nvoid Counter::increment() {\n value++; // This is now completely thread-safe!\n}\n\nint Counter::getValue() const {\n return value;\n}\n

\n\n#### Solution 2: Using std::mutex (Good for complex logic)\nIf your increment logic was more complex (e.g., checking multiple variables at once), you would use a mutex (mutual exclusion) to lock the section of code so only one thread can execute it at a time.\n\n*Update counter.h:\n

cpp\n#include <mutex>\n// ... inside class Counter:\nprivate:\n int value;\n mutable std::mutex mtx; // Add a mutex\n

\n\n
Update counter.cpp:\n

cpp\nvoid Counter::increment() {\n // Locks the mutex. When the function ends, the lock is automatically released.\n std::lock_guard<std::mutex> lock(mtx); \n value++; \n}\n

\n\nIf you apply either of these fixes, rebuild your code, and run ctest again, the GoogleTest suite will output [ PASSED ] 1 test. because all 1,000,000 increments will be successfully counted!"
}This is a submission for the DEV April Fools Challenge

What I Built

Demo

Code

How I Built It

Prize Category

Top comments (0)