Uma váriavel atómica é um primitivo de sincronização que ajuda threads ou processos a garantir que uma operação seja realizada, ou seja, dada a operação nessa váriavel, ela só pode ter dois estados: totalmente completa ou não. Isso faz com que uma vez que ela tenha se iniciado não pode ser parada, o que gera uma garantia que a operação foi realizada não importa o que tenha acontecido, seja uma troca de contexto, uma parada súbita no hardware ou etc.

thread_a -> x++
thread_b -> x++

Nesse exemplo, caso ambas as threads executem ao mesmo tempo, x pode assumir dois valores: 1 ou 2. Isso porque, ambas threads podem ler o valor de x como 0 e incrementar para 1 (ao mesmo tempo) ou as threads podem ler e escrever os valores umas seguidas das outras, gerando o valor 2.

Isso pode ser muito ruim em contextos concorrentes pois pode gerar valores não-probabilísticos, usando atómicos nesse caso faria com que as operações de ler e escrever sempre ocorram na ordem que chegam, criando o valor correto.

Em GO:

package main

import (
	"fmt"
	"sync"
)

var num int
var wait = sync.WaitGroup{}

const TO = 100_000

func main() {

	for range 2 {
		wait.Add(1)
		go func() {
			defer wait.Done()
			for range TO {
				num++
			}
		}()
	}

	wait.Wait()

	fmt.Println(num) // Pode ser 144978, 161332 ou 149767
}

Agora usando atómicos:

package main

import (
	"fmt"
	"sync"
	"sync/atomic"
)

var num atomic.Int32
var wait = sync.WaitGroup{}

const TO = 100_000

func main() {

	for range 2 {
		wait.Add(1)
		go func() {
			defer wait.Done()
			for range TO {
				num.Add(1)
			}
		}()
	}

	wait.Wait()

	fmt.Println(num.Load()) // Sempre vai ser 200_000 

}