Функция atomic.SwapInt64

Функция atomic.SwapInt64 атомарно заменяет значение переменной типа int64 на новое значение и возвращает старое значение, которое было до замены. В первый параметр функция принимает указатель на переменную типа int64, во второй параметр - новое значение типа int64, которое нужно установить.

Операция выполняется атомарно, что гарантирует ее безопасность при конкурентном доступе из нескольких горутин. Это особенно важно при работе с общими данными в многопоточных программах, где обычные операции присваивания могут привести к состояниям гонки.

Синтаксис

goatomic.SwapInt64(addr *int64, new int64) int64

Пример с одной горутиной

Давайте рассмотрим базовое использование функции atomic.SwapInt64 для замены значения переменной:

gopackage main

import (
  "fmt"
  "sync/atomic"
)

func main() {
  var val int64 = 10
  
  old := atomic.SwapInt64(&val, 20)
  
  fmt.Printf("Old value: %d, New value: %d\n", old, val)
}

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

go"Old value: 10, New value: 20"

Пример с несколькими горутинами

Теперь рассмотрим пример, демонстрирующий безопасную замену значения из нескольких горутин:

gopackage main

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

func main() {
  var counter int64 = 0
  var wg sync.WaitGroup
  
  for i := 0; i < 5; i++ {
    wg.Add(1)
    go func(id int) {
      defer wg.Done()
      old := atomic.SwapInt64(&counter, int64(id))
      fmt.Printf("Goroutine %d: old=%d, new=%d\n", id, old, counter)
    }(i)
  }
  
  wg.Wait()
  fmt.Printf("Final counter: %d\n", atomic.LoadInt64(&counter))
}

Результат выполнения кода (порядок может меняться):

go"Goroutine 2: old=0, new=2"
"Goroutine 3: old=2, new=3"
"Goroutine 4: old=3, new=4"
"Goroutine 0: old=4, new=0"
"Goroutine 1: old=0, new=1"
"Final counter: 1"

Пример с использованием в цикле

Давайте рассмотрим, как можно использовать atomic.SwapInt64 для поочередной замены значений в цикле:

gopackage main

import (
  "fmt"
  "sync/atomic"
)

func main() {
  var value int64 = 100
  
  for i := 0; i < 3; i++ {
    old := atomic.SwapInt64(&value, int64(i*10))
    fmt.Printf("Iteration %d: old=%d, new=%d\n", i, old, value)
  }
  
  fmt.Printf("Final value: %d\n", atomic.LoadInt64(&value))
}

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

go"Iteration 0: old=100, new=0"
"Iteration 1: old=0, new=10"
"Iteration 2: old=10, new=20"
"Final value: 20"

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

  • функцию atomic.LoadInt64,
    которая атомарно загружает значение переменной
  • функцию atomic.StoreInt64,
    которая атомарно сохраняет новое значение переменной
  • функцию atomic.CompareAndSwapInt64,
    которая выполняет сравнение и замену значения атомарно
  • функцию atomic.AddInt64,
    которая атомарно прибавляет значение к переменной