Mi az az atom művelet, milyen típusai vannak, és mikor és hogyan érdemes őket használni?
sobes.tech MI
Válasz az MI-től
Atomáris műveletek olyan memória műveletek, amelyek végrehajtása garantáltan vagy teljesen befejeződik, vagy egyáltalán nem kezdődik el, és nem szakíthatók meg más versengő műveletek által. Ezek oszthatatlanok és hardver szinten biztonságosak.
Go nyelvben a sync/atomic csomag funkciókészletet nyújt az atomáris műveletek végrehajtására:
| Funkció | Leírás |
|---|---|
AddInt32 |
int32 értékhez atomárisan hozzáad |
AddInt64 |
int64 értékhez atomárisan hozzáad |
AddUint32 |
uint32 értékhez atomárisan hozzáad |
AddUint64 |
uint64 értékhez atomárisan hozzáad |
AddUintptr |
uintptr értékhez atomárisan hozzáad |
CompareAndSwapInt32 |
Atomáris összehasonlítás és csere (CAS) int32-hez |
CompareAndSwapInt64 |
Atomáris összehasonlítás és csere (CAS) int64-hez |
CompareAndSwapUint32 |
Atomáris összehasonlítás és csere (CAS) uint32-hez |
CompareAndSwapUint64 |
Atomáris összehasonlítás és csere (CAS) uint64-hez |
CompareAndSwapUintptr |
Atomáris összehasonlítás és csere (CAS) uintptr-hez |
LoadInt32 |
int32 érték atomáris betöltése |
LoadInt64 |
int64 érték atomáris betöltése |
LoadUint32 |
uint32 érték atomáris betöltése |
LoadUint64 |
uint64 érték atomáris betöltése |
LoadUintptr |
uintptr érték atomáris betöltése |
LoadPointer |
unsafe.Pointer érték atomáris betöltése |
StoreInt32 |
int32 érték atomáris tárolása |
StoreInt64 |
int64 érték atomáris tárolása |
StoreUint32 |
uint32 érték atomáris tárolása |
StoreUint64 |
uint64 érték atomáris tárolása |
StoreUintptr |
uintptr érték atomáris tárolása |
StorePointer |
unsafe.Pointer érték atomáris tárolása |
SwapInt32 |
int32 érték atomáris cseréje |
SwapInt64 |
int64 érték atomáris cseréje |
SwapUint32 |
uint32 érték atomáris cseréje |
SwapUint64 |
uint64 érték atomáris cseréje |
SwapUintptr |
uintptr érték atomáris cseréje |
SwapPointer |
unsafe.Pointer érték atomáris cseréje |
Az atomáris műveletek használata leginkább akkor ajánlott, amikor egyszerű, alacsony szintű szinkronizációra van szükség a közös változókhoz, általában számlálókhoz vagy zászlókhoz, mutexek használata nélkül. Ezek minimális overheadet biztosítanak és jobb teljesítményt nyújtanak ilyen szcenáriókban.
Atomáris számláló példája:
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árisan növeljük a számlálót
atomic.AddInt64(&counter, 1)
wg.Done()
}()
}
wg.Wait()
// Atomárisan betöltjük a számláló értékét
fmt.Println("Final Counter:", atomic.LoadInt64(&counter))
}
CompareAndSwap használat példája:
package main
import (
"fmt"
"sync/atomic"
)
func main() {
var value int32 = 10
// Megpróbálja kicserélni az értéket, ha az jelenleg 10, 20-ra
swapped := atomic.CompareAndSwapInt32(&value, 10, 20)
fmt.Println("Swapped:", swapped) // Swapped: true
fmt.Println("Value:", value) // Value: 20
// Megpróbálja kicserélni az értéket, ha az jelenleg 10, 30-ra
swapped = atomic.CompareAndSwapInt32(&value, 10, 30)
fmt.Println("Swapped:", swapped) // Swapped: false
fmt.Println("Value:", value) // Value: 20
}
Fontos megjegyezni, hogy az atomáris műveletek csak primitív típusokkal működnek (egész számok, pointerek). Komplexebb adatszerkezetekhez vagy blokkoló műveletekhez továbbra is mutexek vagy más szinkronizációs mechanizmusok szükségesek. Túlzott vagy helytelen használatuk nehezen észrevehető hibákhoz vagy teljesítménycsökkenéshez vezethet.