РЕПЕТИТОР математика физика информатика
Для школьников и студентов. Подтягивание пробелов. ЦЭ, ЦТ, ОГЭ, ЕГЭ.
Идет набор на ЛЕТО. Жмите для подробностей:)
891 of 1593 menu

Функция atomic.CompareAndSwapPointer

Функция atomic.CompareAndSwapPointer атомарно сравнивает значение указателя с ожидаемым значением и, если они равны, заменяет его на новое значение. Операция выполняется атомарно, что гарантирует корректность в многопоточных программах. В первый параметр мы передаем указатель на значение типа unsafe.Pointer, которое нужно сравнить и обновить, во второй параметр передаем ожидаемое значение указателя, в третий параметр передаем новое значение, на которое нужно заменить указатель при успешном сравнении.

Функция возвращает true, если операция обмена прошла успешно, и false, если ожидаемое значение не совпало с текущим. Она полезна для реализации безопасных алгоритмов без блокировок, например, при работе с односвязными списками или для управления состоянием объектов в конкурентной среде.

Важно помнить, что функция работает с типом unsafe.Pointer, поэтому для работы с конкретными типами указателей необходимо выполнять преобразование через unsafe.Pointer. Также следует соблюдать осторожность при работе с этой функцией, так как она обходит систему типов Go.

Синтаксис

atomic.CompareAndSwapPointer(addr *unsafe.Pointer, old, new unsafe.Pointer) bool

Пример

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

package main import ( "fmt" "sync/atomic" "unsafe" ) func main() { var ptr unsafe.Pointer oldValue := "old" newValue := "new" atomic.CompareAndSwapPointer(&ptr, nil, unsafe.Pointer(&oldValue)) fmt.Printf("ptr: %v\n", *(*string)(ptr)) swapped := atomic.CompareAndSwapPointer(&ptr, unsafe.Pointer(&oldValue), unsafe.Pointer(&newValue)) fmt.Printf("swapped: %v, ptr: %v\n", swapped, *(*string)(ptr)) }

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

"ptr: old" "swapped: true, ptr: new"

Пример

Давайте рассмотрим пример, где операция обмена не выполняется из-за несовпадения ожидаемого значения:

package main import ( "fmt" "sync/atomic" "unsafe" ) func main() { val := "initial" var ptr unsafe.Pointer = unsafe.Pointer(&val) expected := "wrong" newVal := "updated" swapped := atomic.CompareAndSwapPointer(&ptr, unsafe.Pointer(&expected), unsafe.Pointer(&newVal)) fmt.Printf("swapped: %v, ptr: %v\n", swapped, *(*string)(ptr)) }

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

"swapped: false, ptr: initial"

Пример

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

package main import ( "fmt" "sync" "sync/atomic" "unsafe" ) type Config struct { Name string Port int } var configPtr unsafe.Pointer func updateConfig(newConfig *Config) bool { oldPtr := atomic.LoadPointer(&configPtr) return atomic.CompareAndSwapPointer(&configPtr, oldPtr, unsafe.Pointer(newConfig)) } func getConfig() *Config { return (*Config)(atomic.LoadPointer(&configPtr)) } func main() { initial := &Config{Name: "default", Port: 8080} atomic.StorePointer(&configPtr, unsafe.Pointer(initial)) var wg sync.WaitGroup for i := 0; i < 100; i++ { wg.Add(1) go func(id int) { defer wg.Done() newConfig := &Config{Name: fmt.Sprintf("config-%d", id), Port: 8000 + id} if updateConfig(newConfig) { fmt.Printf("goroutine %d: updated to %s\n", id, getConfig().Name) } }(i) } wg.Wait() finalConfig := getConfig() fmt.Printf("final config: %s:%d\n", finalConfig.Name, finalConfig.Port) }

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

"goroutine 59: updated to config-59" "goroutine 80: updated to config-80" "goroutine 43: updated to config-43" "goroutine 0: updated to config-0" "goroutine 76: updated to config-76" "goroutine 93: updated to config-93" "goroutine 29: updated to config-29" "goroutine 92: updated to config-92" "goroutine 61: updated to config-61" "goroutine 56: updated to config-56" "goroutine 8: updated to config-8" "goroutine 74: updated to config-74" "goroutine 9: updated to config-9" "goroutine 12: updated to config-12" "goroutine 51: updated to config-51" "goroutine 47: updated to config-47" "goroutine 35: updated to config-35" "goroutine 73: updated to config-73" "goroutine 70: updated to config-70" "goroutine 65: updated to config-65" "goroutine 55: updated to config-55" "goroutine 60: updated to config-60" "goroutine 44: updated to config-44" "goroutine 30: updated to config-30" "goroutine 14: updated to config-14" "goroutine 7: updated to config-7" "goroutine 27: updated to config-27" "goroutine 10: updated to config-10" "goroutine 72: updated to config-72" "goroutine 68: updated to config-68" "goroutine 36: updated to config-36" "goroutine 13: updated to config-13" "goroutine 63: updated to config-63" "goroutine 42: updated to config-42" "goroutine 69: updated to config-69" "goroutine 34: updated to config-34" "goroutine 53: updated to config-53" "goroutine 87: updated to config-87" "goroutine 81: updated to config-81" "goroutine 2: updated to config-2" "goroutine 19: updated to config-19" "goroutine 67: updated to config-67" "goroutine 25: updated to config-25" "goroutine 23: updated to config-23" "goroutine 22: updated to config-22" "goroutine 28: updated to config-28" "goroutine 32: updated to config-32" "goroutine 50: updated to config-50" "goroutine 91: updated to config-91" "goroutine 64: updated to config-64" "goroutine 85: updated to config-85" "goroutine 33: updated to config-33" "goroutine 40: updated to config-40" "goroutine 54: updated to config-54" "goroutine 48: updated to config-48" "goroutine 24: updated to config-24" "goroutine 11: updated to config-11" "goroutine 52: updated to config-52" "goroutine 66: updated to config-66" "goroutine 17: updated to config-17" "goroutine 16: updated to config-16" "goroutine 89: updated to config-89" "goroutine 88: updated to config-88" "goroutine 71: updated to config-71" "goroutine 45: updated to config-45" "goroutine 83: updated to config-83" "goroutine 77: updated to config-77" "goroutine 37: updated to config-37" "goroutine 18: updated to config-18" "goroutine 86: updated to config-86" "goroutine 94: updated to config-94" "goroutine 20: updated to config-20" "goroutine 21: updated to config-21" "goroutine 62: updated to config-62" "goroutine 38: updated to config-38" "goroutine 82: updated to config-82" "goroutine 39: updated to config-39" "goroutine 96: updated to config-96" "goroutine 41: updated to config-41" "goroutine 5: updated to config-5" "goroutine 49: updated to config-49" "goroutine 26: updated to config-26" "goroutine 97: updated to config-97" "goroutine 98: updated to config-98" "goroutine 99: updated to config-99" "goroutine 75: updated to config-75" "goroutine 1: updated to config-1" "goroutine 31: updated to config-31" "goroutine 46: updated to config-46" "goroutine 78: updated to config-78" "goroutine 4: updated to config-4" "goroutine 3: updated to config-3" "goroutine 84: updated to config-84" "goroutine 79: updated to config-79" "goroutine 58: updated to config-58" "goroutine 57: updated to config-57" "goroutine 95: updated to config-95" "goroutine 90: updated to config-90" "goroutine 6: updated to config-6" "goroutine 15: updated to config-15" "final config: config-15:8015"

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

  • функцию atomic.CompareAndSwapInt32,
    которая выполняет атомарное сравнение и обмен для 32-битного целого числа
  • функцию atomic.CompareAndSwapInt64,
    которая выполняет атомарное сравнение и обмен для 64-битного целого числа
  • функцию atomic.SwapPointer,
    которая атомарно заменяет указатель на новое значение без сравнения
  • функцию atomic.LoadPointer,
    которая атомарно загружает значение указателя
Мы используем cookie для работы сайта, аналитики и персонализации. Обработка данных происходит согласно Политике конфиденциальности.
принять все настроить отклонить