C#
atomic operations
thread safety
concurrency
programming

What operations are atomic in C?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In the .NET context, an atomic operation is one that cannot be observed halfway through by another thread. The tricky part is that not every read, write, increment, or compound expression is atomic, and even when an operation is atomic, that does not automatically make a larger algorithm thread-safe.

Atomic Is Smaller Than Thread-Safe

A single atomic read or write can still be part of a broken multi-step sequence. For example, "read value, add one, write it back" is not automatically atomic as a whole just because each simple access looks innocent.

That is why the question matters: you need to know which individual operations are atomic and when to use stronger tools such as Interlocked or locks.

Simple Reads and Writes

In ordinary .NET code, reads and writes of certain primitive values and references are atomic under the runtime guarantees typically relied upon in C# code. But you should be careful not to generalize that into a claim that all compound manipulations are atomic.

This is not atomic as an increment operation:

csharp
counter++;

Even though it looks small, it is conceptually:

  1. Read counter.
  2. Add one.
  3. Write the result back.

Another thread can interfere between those steps.

Use Interlocked for Common Atomic Updates

When you need an atomic increment, decrement, exchange, or compare-and-swap, use the Interlocked class.

csharp
1using System;
2using System.Threading;
3
4class Program
5{
6    static int counter = 0;
7
8    static void Main()
9    {
10        Interlocked.Increment(ref counter);
11        Console.WriteLine(counter);
12    }
13}

Other common operations include:

  • 'Interlocked.Decrement'
  • 'Interlocked.Add'
  • 'Interlocked.Exchange'
  • 'Interlocked.CompareExchange'

These exist specifically because x++ and similar expressions are not enough in multithreaded code.

References and Visibility Are Different Questions

Reference assignment is often described as atomic, but atomicity alone does not solve memory-ordering or visibility questions. One thread may write a value atomically and another may still need the proper synchronization semantics to observe program state correctly.

That is why multithreading discussions often mention both:

  • Atomicity.
  • Memory ordering or visibility.

If you need both correctness and coordination, Interlocked, volatile, or locks may be part of the design depending on the problem.

Locks Still Matter

Not every problem should be solved with atomic primitives alone. If the operation spans multiple state changes, a lock can be the correct solution.

csharp
1using System;
2
3class Counter
4{
5    private int _value;
6    private readonly object _gate = new();
7
8    public void Increment()
9    {
10        lock (_gate)
11        {
12            _value++;
13        }
14    }
15}

A lock is more expensive than a single atomic primitive, but it protects larger invariants that Interlocked.Increment alone cannot express.

Volatile Is Not a Universal Replacement

volatile can affect visibility semantics for specific scenarios, but it is not a substitute for every atomic update pattern. If the operation itself must be indivisible, Interlocked or a lock is still the right tool.

Common Pitfalls

  • Assuming x++ is atomic because it looks like one operation in source code.
  • Confusing an atomic primitive with a thread-safe multi-step algorithm.
  • Using plain reads and writes where Interlocked was actually needed.
  • Ignoring visibility and ordering after focusing only on atomicity.
  • Replacing a necessary lock with atomic primitives even though the real problem spans multiple fields or steps.

Summary

  • Atomic means an operation cannot be observed halfway through by another thread.
  • Simple-looking compound expressions such as counter++ are not atomic as whole updates.
  • Use Interlocked for common atomic numeric and exchange operations.
  • Atomicity alone does not guarantee full thread safety or visibility correctness.
  • Use locks when the invariant spans more than one atomic step.

Course illustration
Course illustration

All Rights Reserved.