Функция atomic.SwapPointer

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

Синтаксис

goatomic.SwapPointer(addr *unsafe.Pointer, new unsafe.Pointer) unsafe.Pointer

Пример

Давайте выполним атомарную замену значения указателя на новое значение:

gopackage main

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

func main() {
  var ptr unsafe.Pointer
  oldValue := "old"
  newValue := "new"

  atomic.StorePointer(&ptr, unsafe.Pointer(&oldValue))

  old := atomic.SwapPointer(&ptr, unsafe.Pointer(&newValue))
  fmt.Println(*(*string)(old))
  fmt.Println(*(*string)(ptr))
}

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

go"old"
"new"

Пример

Давайте используем атомарную замену указателя для безопасного обновления конфигурации в многопоточном приложении:

gopackage main

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

type Config struct {
  Value string
}

func main() {
  var configPtr unsafe.Pointer
  initialConfig := &Config{Value: "v1"}
  atomic.StorePointer(&configPtr, unsafe.Pointer(initialConfig))

  var wg sync.WaitGroup
  wg.Add(2)

  // Горутина читает конфигурацию
  go func() {
    defer wg.Done()
    for i := 0; i < 3; i++ {
      cfg := (*Config)(atomic.LoadPointer(&configPtr))
      fmt.Printf("Read: %s\n", cfg.Value)
    }
  }()

  // Горутина обновляет конфигурацию
  go func() {
    defer wg.Done()
    newConfig := &Config{Value: "v2"}
    old := atomic.SwapPointer(&configPtr, unsafe.Pointer(newConfig))
    fmt.Printf("Swapped from %s to %s\n", (*Config)(old).Value, newConfig.Value)
  }()

  wg.Wait()
}

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

go"Swapped from v1 to v2"
"Read: v2"
"Read: v1"
"Read: v2"

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

  • функцию atomic.SwapInt32,
    которая выполняет атомарную замену значения int32
  • функцию atomic.CompareAndSwapPointer,
    которая атомарно сравнивает и заменяет значение указателя
  • функцию atomic.LoadPointer,
    которая атомарно читает значение указателя
  • функцию atomic.StorePointer,
    которая атомарно записывает значение указателя