Тип atomic.Uint64

Тип atomic.Uint64 представляет собой 64-битное беззнаковое целое число, которое поддерживает атомарные операции. Он определен в пакете sync/atomic и предназначен для безопасного обновления и чтения значений из разных горутин. В отличие от обычного uint64, все методы atomic.Uint64 гарантируют, что операции выполняются атомарно, что исключает состояния гонки.

Основные методы типа atomic.Uint64 включают: Load для атомарного чтения, Store для атомарной записи, Add для атомарного прибавления, Swap для атомарного обмена значениями и CompareAndSwap для атомарного сравнения и обмена. Все операции выполняются с гарантией упорядочивания памяти, что важно для корректной работы в многопоточных программах.

Синтаксис

Для создания атомарного 64-битного беззнакового целого используется функция atomic.Uint64 с последующим вызовом методов:

govar val atomic.Uint64
val.Store(100)
n := val.Load()
val.Add(10)
swapped := val.CompareAndSwap(110, 200)

Инициализация значения может быть выполнена через функцию atomic.Uint64 с начальным значением или через метод Store.

Пример

В этом примере мы создаем атомарный счетчик и инкрементируем его из нескольких горутин:

gopackage main

import (
  "fmt"
  "sync"
  "sync/atomic"
)

func main() {
  var counter atomic.Uint64
  var wg sync.WaitGroup

  for i := 0; i < 10; i++ {
    wg.Add(1)
    go func() {
      defer wg.Done()
      for j := 0; j < 100; j++ {
        counter.Add(1)
      }
    }()
  }

  wg.Wait()
  fmt.Println(counter.Load())
}

Результат выполнения кода:

go1000

Пример

Используем метод CompareAndSwap для атомарной замены значения только в том случае, если оно равно ожидаемому:

gopackage main

import (
  "fmt"
  "sync/atomic"
)

func main() {
  var val atomic.Uint64
  val.Store(42)

  swapped := val.CompareAndSwap(42, 100)
  fmt.Println(swapped)
  fmt.Println(val.Load())

  swapped = val.CompareAndSwap(42, 200)
  fmt.Println(swapped)
  fmt.Println(val.Load())
}

Результат выполнения кода:

gotrue
100
false
100

Пример

Метод Swap атомарно заменяет значение и возвращает предыдущее:

gopackage main

import (
  "fmt"
  "sync/atomic"
)

func main() {
  var val atomic.Uint64
  val.Store(10)

  old := val.Swap(20)
  fmt.Println(old)
  fmt.Println(val.Load())
}

Результат выполнения кода:

go10
20

Смотрите также

  • тип atomic.Int64,
    атомарное 64-битное знаковое целое
  • тип atomic.Uint32,
    атомарное 32-битное беззнаковое целое
  • тип atomic.Bool,
    атомарное логическое значение
  • тип atomic.Pointer,
    атомарный указатель на значение