C++ Multithreading Magic Guide: The Atomic Button Machine

⚛️ std::atomic — The Mysterious Power of the Atomic Button Machine ⚙️

<span>std::atomic</span> is a concurrent primitive provided by C++, allowing you to operate on a variable in a multithreaded environment without needing locks to ensure consistency.

Its core goal:

“To allow multiple threads to read and write to a variable simultaneously without conflicts, without waiting for locks, and still safely.”

1. The Counter Button in the Robot 🤖 Factory

Imagine a robot factory where all robots, after completing assembly, rush to press a counting button. Each press increments the total count by <span>+1</span>, tracking today’s production. Sounds reasonable, right?

But the problem is:

What happens when hundreds of robots rush to press the button simultaneously?

The result is — some robots may press the button but not be counted 😦…..

1.1 Hidden Risks

In fact, this unfortunate outcome occurs because the <span>count++</span> operation is not a single action; it actually consists of three steps 🤔:

1️⃣ Read: Read the current count value from memory  
2️⃣ Add: Increment by 1 in the register  
3️⃣ Write: Write the new value back to memory

In other words:

temp = count;    // Read  
temp = temp + 1; // Add  
count = temp;    // Write

If two robots (threads) execute this simultaneously, it could interleave like this 👇

Time Robot A Robot B Result
T1 Read count=0
T2 Read count=0
T3 Write back count=1
T4 Write back count=1 count=1 ❌

Indeed, it is that subtle ☺️. Even though the button was pressed twice, one press was ignored!!🫨

This is a race condition:

When multiple threads concurrently access shared data, unexpected results can occur.

1.2 Introducing 🥳 The Atomic Button Machine

To solve such bizarre problems, the factory decisively chose to invest in new equipment:

⚙️ Atomic Button Machine <span>std::atomic<int></span>

It uses hardware-level “atomic instructions” to combine those three steps into a single operation.

  • “Read → Modify → Write back” is completed in one atomic step,
  • with no interruptions and no allowance for interleaving.

The underlying assembly might look like this: <span>LOCK XADD [count], 1</span>

When this atomic button is pressed, it will:

  • Lock the bus
  • Perform the addition
  • Write back the result
  • Unlock

The entire process of pressing the button and counting <span>+1</span> is done in one go! The previous bizarre incidents will no longer occur 👻.

1.3 Zooming In 🔍

#include &lt;atomic&gt;

int normalCounter = 0;
std::atomic&lt;int&gt; atomicCounter = 0;

void pressNormalButton() {
    normalCounter++;
    // What actually happens might be like this
    // int temp = normalCounter;   // 1️⃣ Read
    // temp = temp + 1;      // 2️⃣ Add
    // normalCounter = temp;       // 3️⃣ Write
}

void pressAtomicButton() {
    // Simulate atomic button: completed in one go by the CPU
    atomicCounter++;  // ✅ Atomic operation
}

void workAtomic() {
    for (int i = 0; i &lt; 10000; ++i)
        pressAtomicButton();  // Safe even with multiple threads pressing simultaneously
}

2. Atomic Button Machine vs. Mutex <span>mutex</span>

Comparison Item <span>mutex</span> <span>atomic</span>
Granularity A block of code A single variable
Implementation Level Operating System CPU Hardware
Performance Slower Faster
Applicable Scenarios Multi-variable logic Simple counting / Flags

3. The Soul of the Atomic Button Machine (CAS)

This button machine has a super powerful feature called <span>compare_exchange</span><span>:</span>

“If the current value of the machine equals expected, change it to desired; otherwise, do nothing.”

int expected = 0;
int desired = 1;
if (flag.compare_exchange_strong(expected, desired)) {
    std::cout &lt;&lt; "I successfully changed the state!" &lt;&lt; std::endl;
}

This is the foundation of lock-free programming.

In high-concurrency scenarios, it allows threads to coordinate efficiently like a ticketing system.

Less You Forget

  • Normal count++ is a three-step dance: Read → Add → Write;

  • Whereas <span>std::atomic</span> atomic button’s <span>atomicCounter++</span> is a one-step operation: completed in one go, no interruptions allowed.

  • It is not “fast”, but “complete”; not “locked”, but “does not need locks at all”.

  • Supports CAS, if <span>what</span> then <span>this</span> else do nothing 🤷🏿

In the world of concurrency, <span>std::atomic</span><span> is the reliable atomic button machine that never fails.</span>

Leave a Comment