Тип atomic.Int64
Тип atomic.Int64 представляет 64-битное целое число,
с которым можно безопасно работать из разных горутин
без использования мьютексов. Этот тип предоставляет методы
для атомарного чтения, записи, сложения и сравнения значений.
Данный тип находится в пакете sync/atomic и является
рекомендуемой альтернативой функциям вида atomic.LoadInt64
и atomic.StoreInt64, так как предоставляет более удобный
и типобезопасный интерфейс.
Основное преимущество atomic.Int64 заключается в том,
что он гарантирует атомарность операций на аппаратном уровне,
что исключает состояния гонки при конкурентном доступе.
Все методы типа являются потокобезопасными и могут
использоваться в высоконагруженных параллельных системах.
Синтаксис
Для использования типа atomic.Int64 необходимо
импортировать пакет sync/atomic. Создается переменная
типа atomic.Int64, после чего можно вызывать ее методы.
var counter atomic.Int64
counter.Add(10)
val := counter.Load()
Метод Add - атомарное сложение
Метод Add прибавляет переданное значение к текущему
значению atomic.Int64 и возвращает новое значение.
Этот метод работает атомарно и эквивалентен операции
atomic.AddInt64.
package main
import (
"fmt"
"sync"
"sync/atomic"
)
func main() {
var counter atomic.Int64
var wg sync.WaitGroup
for i := 0; i < 100; i++ {
wg.Add(1)
go func() {
defer wg.Done()
newVal := counter.Add(1)
fmt.Printf("New value: %d\n", newVal)
}()
}
wg.Wait()
fmt.Printf("Final counter: %d\n", counter.Load())
}
Результат выполнения кода (порядок чисел может меняться):
"New value: 1"
"New value: 2"
...
"New value: 100"
"Final counter: 100"
Метод Load - атомарное чтение
Метод Load атомарно возвращает текущее значение
atomic.Int64. Он гарантирует, что чтение будет
выполнено целостно, без промежуточных состояний, и
эквивалентен функции atomic.LoadInt64.
package main
import (
"fmt"
"sync/atomic"
)
func main() {
var value atomic.Int64
value.Store(42)
res := value.Load()
fmt.Printf("Loaded value: %d\n", res)
}
Результат выполнения кода:
"Loaded value: 42"
Метод Store - атомарная запись
Метод Store атомарно устанавливает новое значение
для atomic.Int64. Эта операция эквивалентна функции
atomic.StoreInt64 и гарантирует, что запись будет
выполнена атомарно, без промежуточных состояний.
package main
import (
"fmt"
"sync/atomic"
)
func main() {
var value atomic.Int64
value.Store(100)
fmt.Printf("Stored value: %d\n", value.Load())
}
Результат выполнения кода:
"Stored value: 100"
Метод Swap - атомарная замена
Метод Swap атомарно устанавливает новое значение
и возвращает предыдущее. Эта операция эквивалентна функции
atomic.SwapInt64 и полезна, когда нужно получить
старое значение в момент замены.
package main
import (
"fmt"
"sync/atomic"
)
func main() {
var value atomic.Int64
value.Store(10)
old := value.Swap(20)
fmt.Printf("Old value: %d, New value: %d\n", old, value.Load())
}
Результат выполнения кода:
"Old value: 10, New value: 20"
Метод CompareAndSwap - атомарное сравнение с заменой
Метод CompareAndSwap сравнивает текущее значение
с ожидаемым и, если они равны, устанавливает новое значение.
Операция возвращает true, если замена произошла.
Этот метод эквивалентен функции atomic.CompareAndSwapInt64
и является основой для реализации lock-free алгоритмов.
package main
import (
"fmt"
"sync/atomic"
)
func main() {
var value atomic.Int64
value.Store(5)
swapped := value.CompareAndSwap(5, 10)
fmt.Printf("Swapped: %t, Value: %d\n", swapped, value.Load())
swapped = value.CompareAndSwap(5, 20)
fmt.Printf("Swapped: %t, Value: %d\n", swapped, value.Load())
}
Результат выполнения кода:
"Swapped: true, Value: 10"
"Swapped: false, Value: 10"
Пример использования в счетчике
Рассмотрим практический пример использования atomic.Int64
для создания потокобезопасного счетчика, который инкрементируется
из нескольких горутин:
package main
import (
"fmt"
"sync"
"sync/atomic"
)
type Counter struct {
value atomic.Int64
}
func (c *Counter) Inc() int64 {
return c.value.Add(1)
}
func (c *Counter) Get() int64 {
return c.value.Load()
}
func main() {
counter := &Counter{}
var wg sync.WaitGroup
for i := 0; i < 50; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for j := 0; j < 10; j++ {
counter.Inc()
}
}()
}
wg.Wait()
fmt.Printf("Total count: %d\n", counter.Get())
}
Результат выполнения кода:
"Total count: 500"
Смотрите также
-
тип
atomic.Int32,
предоставляющий атомарные операции для 32-битных целых чисел -
тип
atomic.Uint64,
предоставляющий атомарные операции для беззнаковых 64-битных целых чисел -
функцию
atomic.AddInt64,
которая атомарно прибавляет значение к int64 -
тип
atomic.Bool,
предоставляющий атомарные операции для булевых значений