Функция atomic.CompareAndSwapUint64

Функция atomic.CompareAndSwapUint64 выполняет атомарную операцию сравнения и замены для 64-битного целого числа без знака. В первый параметр передается указатель на переменную типа uint64, значение которой нужно сравнить. Во второй параметр передается ожидаемое значение типа uint64. В третий параметр передается новое значение типа uint64, которое будет установлено, если текущее значение переменной совпадает с ожидаемым. Функция возвращает true, если операция прошла успешно, и false, если значение переменной не совпало с ожидаемым.

Синтаксис

goatomic.CompareAndSwapUint64(addr *uint64, old, new uint64) bool

Пример

Давайте создадим переменную типа uint64 со значением 100 и попытаемся заменить её на 200, ожидая текущее значение 100:

gopackage main

import (
  "fmt"
  "sync/atomic"
)

func main() {
  var value uint64 = 100
  old := uint64(100)
  new := uint64(200)

  swapped := atomic.CompareAndSwapUint64(&value, old, new)
  fmt.Printf("swapped: %t, value: %d\n", swapped, value)
}

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

go"swapped: true, value: 200"

Пример

Теперь попытаемся заменить значение с ожидаемым 50, хотя текущее значение равно 200:

gopackage main

import (
  "fmt"
  "sync/atomic"
)

func main() {
  var value uint64 = 200
  old := uint64(50)
  new := uint64(300)

  swapped := atomic.CompareAndSwapUint64(&value, old, new)
  fmt.Printf("swapped: %t, value: %d\n", swapped, value)
}

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

go"swapped: false, value: 200"

Пример

Рассмотрим использование atomic.CompareAndSwapUint64 в конкурентной среде с несколькими горутинами:

gopackage main

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

func main() {
  var counter uint64 = 0
  var wg sync.WaitGroup
  expected := uint64(0)

  for i := 0; i < 1000; i++ {
    wg.Add(1)
    go func() {
      defer wg.Done()
      for {
        old := atomic.LoadUint64(&counter)
        new := old + 1
        if atomic.CompareAndSwapUint64(&counter, old, new) {
          break
        }
      }
    }()
  }

  wg.Wait()
  fmt.Printf("Final counter: %d\n", counter)
}

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

go"Final counter: 1000"

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

  • функцию atomic.CompareAndSwapUint32,
    которая выполняет атомарное сравнение и замену для 32-битного целого без знака
  • функцию atomic.CompareAndSwapInt64,
    которая выполняет атомарное сравнение и замену для 64-битного целого со знаком
  • функцию atomic.CompareAndSwapPointer,
    которая выполняет атомарное сравнение и замену для указателя
  • функцию atomic.SwapUint64,
    которая атомарно заменяет значение без проверки на соответствие