Wat zijn atomare bewerkingen, welke soorten bestaan er en wanneer en hoe is het het beste om ze te gebruiken?
sobes.tech AI
Antwoord van AI
Atomische operaties zijn geheugenbewerkingen waarvan de uitvoering gegarandeerd of volledig wordt voltooid, of helemaal niet begint, en ze kunnen niet worden onderbroken door andere concurrerende operaties. Ze zijn ondeelbaar en hardware-veilig.
In Go biedt het sync/atomic pakket een reeks functies voor het uitvoeren van atomische operaties:
| Functie | Beschrijving |
|---|---|
AddInt32 |
Voegt atomair een waarde toe aan int32. |
AddInt64 |
Voegt atomair een waarde toe aan int64. |
AddUint32 |
Voegt atomair een waarde toe aan uint32. |
AddUint64 |
Voegt atomair een waarde toe aan uint64. |
AddUintptr |
Voegt atomair een waarde toe aan uintptr. |
CompareAndSwapInt32 |
Atomair vergelijken en ruilen (CAS) voor int32. |
CompareAndSwapInt64 |
Atomair vergelijken en ruilen (CAS) voor int64. |
CompareAndSwapUint32 |
Atomair vergelijken en ruilen (CAS) voor uint32. |
CompareAndSwapUint64 |
Atomair vergelijken en ruilen (CAS) voor uint64. |
CompareAndSwapUintptr |
Atomair vergelijken en ruilen (CAS) voor uintptr. |
LoadInt32 |
Atomair laden van een int32 waarde. |
LoadInt64 |
Atomair laden van een int64 waarde. |
LoadUint32 |
Atomair laden van een uint32 waarde. |
LoadUint64 |
Atomair laden van een uint64 waarde. |
LoadUintptr |
Atomair laden van een uintptr. |
LoadPointer |
Atomair laden van een unsafe.Pointer. |
StoreInt32 |
Atomair opslaan van een int32. |
StoreInt64 |
Atomair opslaan van een int64. |
StoreUint32 |
Atomair opslaan van een uint32. |
StoreUint64 |
Atomair opslaan van een uint64. |
StoreUintptr |
Atomair opslaan van een uintptr. |
StorePointer |
Atomair opslaan van een unsafe.Pointer. |
SwapInt32 |
Atomair ruilen van een int32. |
SwapInt64 |
Atomair ruilen van een int64. |
SwapUint32 |
Atomair ruilen van een uint32. |
SwapUint64 |
Atomair ruilen van een uint64. |
SwapUintptr |
Atomair ruilen van een uintptr. |
SwapPointer |
Atomair ruilen van een unsafe.Pointer. |
Het gebruik van atomische operaties is het meest geschikt voor eenvoudige, laag-niveau synchronisatie van gedeelde variabelen, meestal tellers of vlaggen, zonder gebruik te maken van mutexen. Ze bieden minimale overhead en betere prestaties in dergelijke scenario's.
Voorbeeld van het gebruik van een atomische teller:
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() {
// Atomair verhogen van de teller
atomic.AddInt64(&counter, 1)
wg.Done()
}()
}
wg.Wait()
// Atomair laden van de tellerwaarde
fmt.Println("Final Counter:", atomic.LoadInt64(&counter))
}
Voorbeeld van het gebruik van CompareAndSwap:
package main
import (
"fmt"
"sync/atomic"
)
func main() {
var value int32 = 10
// Poging om de waarde te ruilen als deze gelijk is aan 10, naar 20
swapped := atomic.CompareAndSwapInt32(&value, 10, 20)
fmt.Println("Swapped:", swapped) // Swapped: true
fmt.Println("Value:", value) // Value: 20
// Poging om de waarde te ruilen als deze gelijk is aan 10, naar 30
swapped = atomic.CompareAndSwapInt32(&value, 10, 30)
fmt.Println("Swapped:", swapped) // Swapped: false
fmt.Println("Value:", value) // Value: 20
}
Belangrijk: atomische operaties werken alleen met primitieve types (gehele getallen, pointers). Voor synchronisatie van toegang tot complexere datastructuren of het uitvoeren van blokkerende operaties zijn nog steeds mutexen of andere synchronisatie-mechanismen nodig. Overmatig of verkeerd gebruik van atomische operaties kan leiden tot moeilijk te traceren fouten of verminderde prestaties.