Подтвердить что ты не робот

Назначает ли указатель атома в golang?

Назначение атома указателя в go?

Нужно ли назначать указатель в блокировке? Предположим, я просто хочу назначить указатель на нуль и хотел бы, чтобы другие потоки могли его видеть. Я знаю, что в java мы можем использовать volatile для этого. Но нет никакой изменчивости в движении.

Спасибо.

4b9b3361

Ответ 1

Единственными вещами, которые гарантированно являются атомарными в go, являются операции в sync.atomic.

Итак, если вы хотите быть уверенным, что вам нужно будет сделать блокировку, например sync.Mutex или использовать один из атомных примитивов. Я не рекомендую использовать атомарные примитивы, хотя вам придется использовать их везде, где вы используете указатель, и их трудно получить.

Использование мьютекса в порядке go style - вы можете определить функцию для быстрого возврата текущего указателя с блокировкой, например, что-то вроде

import "sync"

var secretPointer *int
var pointerLock sync.Mutex

func CurrentPointer() *int {
    pointerLock.Lock()
    defer pointerLock.Unlock()
    return secretPointer
}

func SetPointer(p *int) {
    pointerLock.Lock()
    secretPointer = p
    pointerLock.Unlock()
}

Эти функции возвращают копию указателя на их клиентов, которые останутся постоянными, даже если главный указатель будет изменен. Это может быть или не быть приемлемым в зависимости от времени, требующего вашего требования. Этого должно быть достаточно, чтобы избежать любого поведения undefined - сборщик мусора гарантирует, что указатели остаются действительными во все времена, даже если указанная память больше не используется вашей программой.

Альтернативный подход состоял бы в том, чтобы сделать доступ только для указателя из одной процедуры и использовать каналы для управления, которые подталкивают к выполнению действий. Это будет считаться более идиоматичным, но может не соответствовать вашему приложению.

Обновление

Вот пример, показывающий, как использовать atomic.SetPointer. Это довольно уродливо из-за использования unsafe.Pointer. Однако unsafe.Pointer делает компиляцию ни к чему, поэтому стоимость исполнения невелика.

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

type Struct struct {
    p unsafe.Pointer // some pointer
}

func main() {
    data := 1

    info := Struct{p: unsafe.Pointer(&data)}

    fmt.Printf("info is %d\n", *(*int)(info.p))

    otherData := 2

    atomic.StorePointer(&info.p, unsafe.Pointer(&otherData))

    fmt.Printf("info is %d\n", *(*int)(info.p))

}

Ответ 2

Поскольку спецификация не указывает, вы должны предположить, что это не так. Даже если он в настоящее время является атомарным, возможно, что он может измениться, даже не нарушая спецификацию.