an atomic operation
Atomic comes from the Greek for 'indivisible.' An atomic operation is one that, as far as any other thread can tell, happens all at once — there is no observable in-between state. It is like flipping a light switch: it is either off or on, never caught halfway. The reason this matters is that operations we write as a single line of code are usually not single steps for the hardware. The familiar count = count + 1 actually compiles to three machine steps: read count from memory into a register, add one, write the register back. If two threads interleave those steps, both can read the same old value and both write back the same new value, and one increment is silently lost. The whole point of an atomic operation is to make such an update indivisible so this cannot happen.
Modern CPUs provide a handful of atomic instructions as hardware primitives. The most basic is an atomic read-modify-write such as fetch-and-add (atomically read a value and add to it) or test-and-set (atomically read a flag and set it). The most important and general is compare-and-swap, written CAS(address, expected, new): it atomically checks whether the memory at address still holds expected, and only if so writes new, reporting whether it succeeded. The CPU enforces this indivisibility at the memory-bus or cache level, so no other core can sneak a conflicting access in the middle. Programming languages expose these as atomic types (for example a C or C++ atomic integer, or Java's AtomicInteger) whose increment, exchange, and compare-and-swap methods are guaranteed atomic.
Atomics are the foundation that everything else in concurrency is built on. Locks themselves are implemented with atomic test-and-set or compare-and-swap; lock-free data structures use atomics directly to avoid locks entirely. But two honest cautions. First, atomicity of one operation does not make a sequence of operations atomic: doing two separate atomic updates is not the same as updating both together — for that you still need a lock or a transaction. Second, atomicity is about indivisibility, which is a separate guarantee from visibility ordering; on a relaxed memory model you may also need memory barriers to control when other threads see the result. Atomic means 'all-or-nothing,' not automatically 'immediately seen by everyone in order.'
Lost update without atomicity: count = 0. Thread A reads 0, thread B reads 0, A computes 1 and writes 1, B computes 1 and writes 1. Two increments, but count is 1. An atomic fetch-and-add makes each increment indivisible, so the result is correctly 2.
The lost-update race that atomics exist to prevent — three machine steps interleaving where the source looked like one.
Atomicity of a single instruction does not compose: two atomic operations done one after another are not jointly atomic, and another thread can observe the state in between. Bundling several updates atomically still needs a lock or transactional memory.