Метод sync.Map.CompareAndSwap
Метод sync.Map.CompareAndSwap выполняет атомарную операцию сравнения и замены значения для указанного ключа. В первый параметр мы передаем ключ, значение которого нужно проверить и заменить. Во второй параметр мы передаем ожидаемое значение, с которым сравнивается текущее значение по ключу. В третий параметр мы передаем новое значение, которое будет установлено, если сравнение прошло успешно. Метод возвращает true, если операция выполнена, и false, если текущее значение не соответствует ожидаемому.
Синтаксис
m.CompareAndSwap(key, old, new)
Пример
Давайте создадим sync.Map, добавим в него ключ со значением и попробуем заменить значение атомарно:
package main
import (
"fmt"
"sync"
)
func main() {
var m sync.Map
m.Store("counter", 10)
swapped := m.CompareAndSwap("counter", 10, 20)
fmt.Printf("swapped: %t\n", swapped)
value, _ := m.Load("counter")
fmt.Printf("value: %d\n", value)
}
Результат выполнения кода:
"swapped: true"
"value: 20"
Пример
Попробуем заменить значение, которое не соответствует ожидаемому:
package main
import (
"fmt"
"sync"
)
func main() {
var m sync.Map
m.Store("counter", 10)
swapped := m.CompareAndSwap("counter", 15, 20)
fmt.Printf("swapped: %t\n", swapped)
value, _ := m.Load("counter")
fmt.Printf("value: %d\n", value)
}
Результат выполнения кода:
"swapped: false"
"value: 10"
Пример
Давайте рассмотрим пример использования CompareAndSwap в конкурентной среде, где несколько горутин пытаются одновременно увеличить счетчик:
package main
import (
"fmt"
"sync"
)
func main() {
var m sync.Map
var wg sync.WaitGroup
m.Store("counter", 0)
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for {
oldVal, _ := m.Load("counter")
old := oldVal.(int)
newVal := old + 1
if m.CompareAndSwap("counter", old, newVal) {
break
}
}
}()
}
wg.Wait()
value, _ := m.Load("counter")
fmt.Printf("final counter: %d\n", value)
}
Результат выполнения кода:
"final counter: 10"
Смотрите также
-
метод
sync.Map.CompareAndDelete,
который атомарно удаляет ключ при совпадении значения -
метод
sync.Map.Swap,
который атомарно заменяет значение и возвращает старое -
метод
sync.Map.Store,
который устанавливает значение для ключа -
метод
sync.Map.Load,
который возвращает значение по ключу