Функция atomic.CompareAndSwapUint32

Функция atomic.CompareAndSwapUint32 выполняет атомарную операцию сравнения и замены (compare-and-swap) для значения типа uint32. Эта операция является ключевым примитивом синхронизации в конкурентном программировании. В качестве первого аргумента она принимает указатель на uint32, который нужно сравнить и изменить, вторым аргументом - ожидаемое значение, и третьим - новое значение, на которое будет заменено старое, если они совпадают. Функция возвращает true, если операция выполнена успешно, и false в противном случае.

Синтаксис

goatomic.CompareAndSwapUint32(addr *uint32, old uint32, new uint32) bool

Пример

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

gopackage main

import (
  "fmt"
  "sync/atomic"
)

func main() {
  var value uint32 = 10

  swapped := atomic.CompareAndSwapUint32(&value, 10, 20)
  fmt.Printf("Operation result: %t, value: %d\n", swapped, value)

  swapped = atomic.CompareAndSwapUint32(&value, 10, 30)
  fmt.Printf("Operation result: %t, value: %d\n", swapped, value)
}

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

go"Operation result: true, value: 20"
"Operation result: false, value: 20"

Пример

Продемонстрируем использование функции для атомарного инкремента в конкурентной среде:

gopackage main

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

func main() {
  var counter uint32 = 0
  var wg sync.WaitGroup
  const goroutines = 1000

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

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

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

go"Final counter value: 1000"

Пример

Рассмотрим пример использования функции для реализации простого атомарного флага:

gopackage main

import (
  "fmt"
  "sync/atomic"
)

func main() {
  var flag uint32 = 0

  if atomic.CompareAndSwapUint32(&flag, 0, 1) {
    fmt.Println("Flag set successfully")
  }

  if atomic.CompareAndSwapUint32(&flag, 0, 1) {
    fmt.Println("Flag set successfully again")
  }

  fmt.Printf("Final flag value: %d\n", flag)
}

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

go"Flag set successfully"
"Final flag value: 1"

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

  • функцию atomic.CompareAndSwapInt32,
    которая выполняет атомарную замену для 32-битного целого числа со знаком
  • функцию atomic.CompareAndSwapUint64,
    которая работает с 64-битными беззнаковыми числами
  • функцию atomic.LoadUint32,
    которая атомарно загружает значение 32-битного числа без знака
  • функцию atomic.StoreUint32,
    которая атомарно записывает значение 32-битного числа без знака