Kas ir atomu operācijas, kādi ir to veidi un kad un kā labāk tās izmantot?
sobes.tech AI
Atbilde no AI
Atomārās operācijas ir operācijas ar atmiņu, kuru izpilde tiek garantēti vai nu pilnībā, vai vispār nesākas, un tās nevar pārtraukt citas konkurējošas operācijas. Tās ir nedalāmas un aparatūras līmenī drošas.
Go pakotne sync/atomic nodrošina funkciju kopumu atomāru operāciju veikšanai:
| Funkcija | Apraksts |
|---|---|
AddInt32 |
Atomāri pievieno vērtību int32. |
AddInt64 |
Atomāri pievieno vērtību int64. |
AddUint32 |
Atomāri pievieno vērtību uint32. |
AddUint64 |
Atomāri pievieno vērtību uint64. |
AddUintptr |
Atomāri pievieno vērtību uintptr. |
CompareAndSwapInt32 |
Atomāri salīdzina un apmaina (CAS) int32. |
CompareAndSwapInt64 |
Atomāri salīdzina un apmaina (CAS) int64. |
CompareAndSwapUint32 |
Atomāri salīdzina un apmaina (CAS) uint32. |
CompareAndSwapUint64 |
Atomāri salīdzina un apmaina (CAS) uint64. |
CompareAndSwapUintptr |
Atomāri salīdzina un apmaina (CAS) uintptr. |
CompareAndSwapPointer |
Atomāri salīdzina un apmaina (CAS) unsafe.Pointer. |
LoadInt32 |
Atomāri ielādē vērtību int32. |
LoadInt64 |
Atomāri ielādē vērtību int64. |
LoadUint32 |
Atomāri ielādē vērtību uint32. |
LoadUint64 |
Atomāri ielādē vērtību uint64. |
LoadUintptr |
Atomāri ielādē vērtību uintptr. |
LoadPointer |
Atomāri ielādē vērtību unsafe.Pointer. |
StoreInt32 |
Atomāri saglabā vērtību int32. |
StoreInt64 |
Atomāri saglabā vērtību int64. |
StoreUint32 |
Atomāri saglabā vērtību uint32. |
StoreUint64 |
Atomāri saglabā vērtību uint64. |
StoreUintptr |
Atomāri saglabā vērtību uintptr. |
StorePointer |
Atomāri saglabā vērtību unsafe.Pointer. |
SwapInt32 |
Atomāri apmaina vērtības int32. |
SwapInt64 |
Atomāri apmaina vērtības int64. |
SwapUint32 |
Atomāri apmaina vērtības uint32. |
SwapUint64 |
Atomāri apmaina vērtības uint64. |
SwapUintptr |
Atomāri apmaina vērtības uintptr. |
SwapPointer |
Atomāri apmaina vērtības unsafe.Pointer. |
Atomāru operāciju izmantošana ir vislabākā gadījumos, kad nepieciešama vienkārša, zema līmeņa piekļuve kopīgajiem mainīgajiem, bieži skaitītājiem vai zīmjiem, bez slēdžiem. Tās nodrošina minimālas izmaksas un labāku veiktspēju salīdzinājumā ar slēdžiem šādos scenārijos.
Piemērs ar atomāru skaitītāju:
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āri palielinām skaitītāju
atomic.AddInt64(&counter, 1)
wg.Done()
}()
}
wg.Wait()
// Atomāri ielādē skaitītāja vērtību
fmt.Println("Galīgais skaitītājs:", atomic.LoadInt64(&counter))
}
Piemērs ar CompareAndSwap:
package main
import (
"fmt"
"sync/atomic"
)
func main() {
var value int32 = 10
// Mēģinājums apmainīt vērtību, ja tā ir 10, uz 20
swapped := atomic.CompareAndSwapInt32(&value, 10, 20)
fmt.Println("Mainīts:", swapped) // Mainīts: true
fmt.Println("Vērtība:", value) // Vērtība: 20
// Mēģinājums apmainīt vērtību, ja tā ir 10, uz 30
swapped = atomic.CompareAndSwapInt32(&value, 10, 30)
fmt.Println("Mainīts:", swapped) // Mainīts: false
fmt.Println("Vērtība:", value) // Vērtība: 20
}
Svarīgi atcerēties, ka atomāras operācijas darbojas ar primītiem datu tipiem (veseliem skaitļiem, norādēm). Lai sinhronizētu piekļuvi uz sarežģītākām datu struktūrām vai veiktu bloķējošas operācijas, joprojām ir nepieciešami slēdži vai citi sinhronizācijas mehānismi. Pārmērīga vai nepareiza atomāru operāciju izmantošana var novest pie grūti uztveramu kļūdu vai veiktspējas samazināšanās.