Challenge 2: Two Fixes — lock_guard and std::atomic — Possible Solution ==================================================================== FIX 1 — std::lock_guard: #include #include #include int counter = 0; std::mutex lock; void increment() { for (int i = 0; i < 100000; i++) { std::lock_guard guard(lock); counter++; } } int main() { std::thread t1(increment); std::thread t2(increment); t1.join(); t2.join(); std::cout << "lock_guard result: " << counter << std::endl; return 0; } FIX 2 — std::atomic, no lock at all: #include #include #include std::atomic counter{0}; void increment() { for (int i = 0; i < 100000; i++) { counter++; } } int main() { std::thread t1(increment); std::thread t2(increment); t1.join(); t2.join(); std::cout << "atomic result: " << counter << std::endl; return 0; } Both, run several times: lock_guard result: 200000 atomic result: 200000 WHY THIS WORKS AS AN ANSWER ------------------------------ Both fixes produce a consistent, correct 200000 on every run, but via genuinely different mechanisms: lock_guard ensures only one thread executes the counter++ critical section at a time (mutual exclusion, RAII-managed), while std::atomic makes counter++ itself a single, indivisible hardware-level operation with no critical section or lock needed at all -- exactly the two distinct approaches the chapter describes, both resolving the same underlying race.