Функция atomic.LoadPointer
Функция atomic.LoadPointer атомарно загружает значение указателя,
на которое ссылается аргумент *unsafe.Pointer. Она гарантирует,
что чтение выполняется как единая неделимая операция в условиях конкурентного
доступа. В первый параметр передается адрес переменной типа
unsafe.Pointer, значение которой нужно загрузить. Функция возвращает
загруженное значение указателя.
Синтаксис
atomic.LoadPointer(addr *unsafe.Pointer) unsafe.Pointer
Пример
Давайте создадим указатель на строку и атомарно загрузим его значение:
package main
import (
"fmt"
"sync/atomic"
"unsafe"
)
func main() {
str := "abcde"
ptr := unsafe.Pointer(&str)
res := atomic.LoadPointer(&ptr)
fmt.Println(*(*string)(res))
}
Результат выполнения кода:
"abcde"
Пример
Рассмотрим атомарное чтение указателя в конкурентной среде с использованием нескольких горутин:
package main
import (
"fmt"
"sync"
"sync/atomic"
"unsafe"
)
func main() {
var wg sync.WaitGroup
var ptr unsafe.Pointer
val := "12345"
ptr = unsafe.Pointer(&val)
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
defer wg.Done()
res := atomic.LoadPointer(&ptr)
fmt.Println(*(*string)(res))
}()
}
wg.Wait()
}
Результат выполнения кода (порядок строк может отличаться):
"12345"
"12345"
"12345"
"12345"
"12345"
"12345"
"12345"
"12345"
"12345"
"12345"
Пример
Приведем пример сравнения атомарной и неатомарной загрузки указателя. Атомарная загрузка гарантирует, что мы прочитаем целостное значение, в то время как при обычном чтении возможна ситуация, когда значение успело измениться во время чтения:
package main
import (
"fmt"
"sync"
"sync/atomic"
"unsafe"
)
func main() {
var wg sync.WaitGroup
var ptr unsafe.Pointer
val1 := "abcde"
val2 := "12345"
ptr = unsafe.Pointer(&val1)
for i := 0; i < 5; i++ {
wg.Add(1)
go func() {
defer wg.Done()
atomic.StorePointer(&ptr, unsafe.Pointer(&val2))
}()
}
for i := 0; i < 5; i++ {
wg.Add(1)
go func() {
defer wg.Done()
res := atomic.LoadPointer(&ptr)
fmt.Println(*(*string)(res))
}()
}
wg.Wait()
}
Результат выполнения кода (порядок строк может отличаться):
"12345"
"12345"
"12345"
"12345"
"12345"
"abcde"
"abcde"
"abcde"
"abcde"
"abcde"
Смотрите также
-
функцию
atomic.StorePointer,
которая атомарно записывает значение указателя -
функцию
atomic.SwapPointer,
которая атомарно заменяет значение указателя и возвращает старое -
функцию
atomic.CompareAndSwapPointer,
которая атомарно сравнивает и заменяет значение указателя -
тип
atomic.Pointer,
который предоставляет типизированную атомарную работу с указателями