Sobes.tech
Middle+

Čo sú atómové operácie, aké druhy existujú a kedy a ako je najlepšie ich používať?

sobes.tech AI

Odpoveď od AI

Atomárne operácie sú operácie nad pamäťou, ktorého vykonanie je garantované, že sa ukončí buď úplne, alebo vôbec nezačne, a nemôžu byť prerušené inými konkurenčnými operáciami. Sú nedeliteľné a bezpečné pre vlákna na hardvérovom úrovni.

V Go balíku sync/atomic poskytuje súbor funkcií na vykonávanie atomárnych operácií:

Funkcia Popis
AddInt32 Atomárne pridáva hodnotu k int32.
AddInt64 Atomárne pridáva hodnotu k int64.
AddUint32 Atomárne pridáva hodnotu k uint32.
AddUint64 Atomárne pridáva hodnotu k uint64.
AddUintptr Atomárne pridáva hodnotu k uintptr.
CompareAndSwapInt32 Atomárne porovnáva a mení (CAS) int32.
CompareAndSwapInt64 Atomárne porovnáva a mení (CAS) int64.
CompareAndSwapUint32 Atomárne porovnáva a mení (CAS) uint32.
CompareAndSwapUint64 Atomárne porovnáva a mení (CAS) uint64.
CompareAndSwapUintptr Atomárne porovnáva a mení (CAS) uintptr.
CompareAndSwapPointer Atomárne porovnáva a mení (CAS) unsafe.Pointer.
LoadInt32 Atomárne načítava hodnotu int32.
LoadInt64 Atomárne načítava hodnotu int64.
LoadUint32 Atomárne načítava hodnotu uint32.
LoadUint64 Atomárne načítava hodnotu uint64.
LoadUintptr Atomárne načítava hodnotu uintptr.
LoadPointer Atomárne načítava hodnotu unsafe.Pointer.
StoreInt32 Atomárne ukladá hodnotu int32.
StoreInt64 Atomárne ukladá hodnotu int64.
StoreUint32 Atomárne ukladá hodnotu uint32.
StoreUint64 Atomárne ukladá hodnotu uint64.
StoreUintptr Atomárne ukladá hodnotu uintptr.
StorePointer Atomárne ukladá hodnotu unsafe.Pointer.
SwapInt32 Atomárne mení hodnoty int32.
SwapInt64 Atomárne mení hodnoty int64.
SwapUint32 Atomárne mení hodnoty uint32.
SwapUint64 Atomárne mení hodnoty uint64.
SwapUintptr Atomárne mení hodnoty uintptr.
SwapPointer Atomárne mení hodnoty unsafe.Pointer.

Používanie atomárnych operácií je najlepšie v prípadoch, keď je potrebná jednoduchá, nízkoúrovňová synchronizácia prístupu k spoločným premenným, najčastejšie čítačom alebo flagom, bez použitia mutexov. Zabezpečujú minimálne náklady a lepší výkon v porovnaní s mutexmi v takých scenároch.

Príklad použitia atomárneho čítača:

package main

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

func main() {
	var counter int64
	var wg sync.WaitGroup

	for i := 0; i < 100; i++ {
		wg.Add(1)
		go func() {
			// Atomárne zvyšujeme čítač
			atomic.AddInt64(&counter, 1)
			wg.Done()
		}()
	}

	wg.Wait()
	// Atomárne načítavame hodnotu čítača
	fmt.Println("Final Counter:", atomic.LoadInt64(&counter))
}

Príklad použitia CompareAndSwap:

package main

import (
	"fmt"
	"sync/atomic"
)

func main() {
	var value int32 = 10

	// Pokus o výmenu, ak je aktuálna hodnota 10, na 20
	swapped := atomic.CompareAndSwapInt32(&value, 10, 20)
	fmt.Println("Swapped:", swapped) // Swapped: true
	fmt.Println("Value:", value)   // Value: 20

	// Pokus o výmenu, ak je aktuálna hodnota 10, na 30
	swapped = atomic.CompareAndSwapInt32(&value, 10, 30)
	fmt.Println("Swapped:", swapped) // Swapped: false
	fmt.Println("Value:", value)   // Value: 20
}