Sobes.tech
Middle+

Šta su atomarne operacije, koje vrste postoje i kada i kako ih je najbolje koristiti?

sobes.tech АИ

Одговор од АИ

Атомарне операције су операције над меморијом, чије извршавање је гарантовано да се завршава или потпуно, или уопште не почиње, и не могу бити прекинуте другим конкурирајућим операцијама. Оне су недељиве и безбедне за токове на хардверском нивоу.

У Go пакету sync/atomic пружа се скуп функција за извршавање атомарних операција:

Функција Опис
AddInt32 Атомарно додаје вредност int32.
AddInt64 Атомарно додаје вредност int64.
AddUint32 Атомарно додаје вредност uint32.
AddUint64 Атомарно додаје вредност uint64.
AddUintptr Атомарно додаје вредност uintptr.
CompareAndSwapInt32 Атомарно упоређује и мења (CAS) int32.
CompareAndSwapInt64 Атомарно упоређује и мења (CAS) int64.
CompareAndSwapUint32 Атомарно упоређује и мења (CAS) uint32.
CompareAndSwapUint64 Атомарно упоређује и мења (CAS) uint64.
CompareAndSwapUintptr Атомарно упоређује и мења (CAS) uintptr.
CompareAndSwapPointer Атомарно упоређује и мења (CAS) unsafe.Pointer.
LoadInt32 Атомарно учитава вредност int32.
LoadInt64 Атомарно учитава вредност int64.
LoadUint32 Атомарно учитава вредност uint32.
LoadUint64 Атомарно учитава вредност uint64.
LoadUintptr Атомарно учитава вредност uintptr.
LoadPointer Атомарно учитава вредност unsafe.Pointer.
StoreInt32 Атомарно чува вредност int32.
StoreInt64 Атомарно чува вредност int64.
StoreUint32 Атомарно чува вредност uint32.
StoreUint64 Атомарно чува вредност uint64.
StoreUintptr Атомарно чува вредност uintptr.
StorePointer Атомарно чува вредност unsafe.Pointer.
SwapInt32 Атомарно мења вредности int32.
SwapInt64 Атомарно мења вредности int64.
SwapUint32 Атомарно мења вредности uint32.
SwapUint64 Атомарно мења вредности uint64.
SwapUintptr Атомарно мења вредности uintptr.
SwapPointer Атомарно мења вредности unsafe.Pointer.

Коришћење атомарних операција је најбоље у случајевима када је потребна једноставна, нискоуровњска синхронизација приступа заједничким променљивим, најчешће бројачима или флаговима, без коришћења мьютексова. Они обезбеђују минималне трошкове и бољу перформансу у поређењу са мьютексима у таквим сценаријима.

Пример коришћења атомарног бројача:

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() {
			// Атомарно увећавамо бројач
			atomic.AddInt64(&counter, 1)
			wg.Done()
		}()
	}

	wg.Wait()
	// Атомарно учитавамо вредност бројача
	fmt.Println("Final Counter:", atomic.LoadInt64(&counter))
}

Пример коришћења CompareAndSwap:

package main

import (
	"fmt"
	"sync/atomic"
)

func main() {
	var value int32 = 10

	// Покушај замене ако је тренутна вредност 10, на 20
	swapped := atomic.CompareAndSwapInt32(&value, 10, 20)
	fmt.Println("Swapped:", swapped) // Swapped: true
	fmt.Println("Value:", value)   // Value: 20

	// Покушај замене ако је тренутна вредност 10, на 30
	swapped = atomic.CompareAndSwapInt32(&value, 10, 30)
	fmt.Println("Swapped:", swapped) // Swapped: false
	fmt.Println("Value:", value)   // Value: 20
}