sync/atomic.Int32 în Go

Un int32 cu operații atomice (Add, Load, Store, Swap, CompareAndSwap); la fel ca atomic.Int64, dar pe 32 de biți.

Sintaxă
var n atomic.Int32
func (x *Int32) Add(delta int32) (new int32)
func (x *Int32) Load() int32
func (x *Int32) Store(val int32)
func (x *Int32) Swap(new int32) (old int32)
func (x *Int32) CompareAndSwap(old, new int32) (swapped bool)

Ce face sync/atomic.Int32

atomic.Int32 funcționează exact ca atomic.Int64, cu valori int32 (până la aproximativ 2,1 miliarde). Ocupă mai puțină memorie, deci e potrivit pentru valori mici: conexiuni active, lucrători ocupați, stări codate ca numere.

Pachetul are aceleași tipuri și pentru numere fără semn: atomic.Uint32, atomic.Uint64, atomic.Uintptr. Pentru contoare care pot crește mult, alege Int64.

Ce returnează

Ca la atomic.Int64, dar cu int32.

Exemple

Exemplul 1: Conexiuni active și vârful lor

package main

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

func main() {
	var active, varf atomic.Int32
	var wg sync.WaitGroup
	for range 8 {
		wg.Go(func() {
			n := active.Add(1)
			for {
				v := varf.Load()
				if n <= v || varf.CompareAndSwap(v, n) {
					break
				}
			}
			time.Sleep(30 * time.Millisecond) // conexiunea e deschisă
			active.Add(-1)
		})
	}
	wg.Wait()
	fmt.Println("Conexiuni active la final:", active.Load())
	fmt.Println("Vârful a fost cel puțin 1:", varf.Load() >= 1)
}

Rezultat

Conexiuni active la final: 0
Vârful a fost cel puțin 1: true

Exemplul 2: Stare codată ca număr

package main

import (
	"fmt"
	"sync/atomic"
)

const (
	Oprit int32 = iota
	Pornire
	Activ
)

var nume = []string{"oprit", "pornire", "activ"}

func main() {
	var stare atomic.Int32
	fmt.Println("Stare:", nume[stare.Load()])
	if stare.CompareAndSwap(Oprit, Pornire) {
		fmt.Println("Pornesc serviciul...")
	}
	if stare.CompareAndSwap(Oprit, Pornire) {
		fmt.Println("Nu apare: nu mai era oprit")
	}
	vechi := stare.Swap(Activ)
	fmt.Println("Din", nume[vechi], "în", nume[stare.Load()])
}

Rezultat

Stare: oprit
Pornesc serviciul...
Din pornire în activ

Greșeli frecvente

  • Folosești Int32 pentru un contor care poate depăși 2.147.483.647: valoarea trece pe negativ fără nicio eroare. Alege Int64.

Comenzi înrudite

  • sync/atomic.Int64: Un int64 cu operații atomice ca metode (Add, Load, Store, Swap); varianta recomandată pentru contoare între goroutine.
  • sync/atomic.Bool: O valoare true/false citită și scrisă atomic; bună pentru steaguri ca „închis”, „pregătit” sau „rulează deja”.
  • sync/atomic.Int64.CompareAndSwap: Scrie valoarea nouă doar dacă valoarea curentă este cea așteptată; baza operațiilor atomice proprii, cu reîncercare.