猿问

在 Go 中分配指针是原子的吗?

在 Go 中分配指针是原子的吗?

我需要在锁中分配一个指针吗?假设我只想将指针分配给 nil,并希望其他线程能够看到它。我知道在 Java 中我们可以为此使用 volatile,但在 Go 中没有 volatile。


慕尼黑8549860
浏览 358回答 3
3回答

翻过高山走不出你

在 go 中唯一保证原子性的是sync.atomic中的操作。因此,如果您想确定您要么需要锁定,例如sync.Mutex,要么使用原子原语之一。我不建议使用原子原语,因为你必须在任何使用指针的地方使用它们,而且它们很难正确使用。使用互斥锁是可以的 - 您可以定义一个函数来非常容易地通过锁定返回当前指针,例如类似的东西import "sync"var secretPointer *intvar pointerLock sync.Mutexfunc CurrentPointer() *int {    pointerLock.Lock()    defer pointerLock.Unlock()    return secretPointer}func SetPointer(p *int) {    pointerLock.Lock()    secretPointer = p    pointerLock.Unlock()}这些函数将指针的副本返回给它们的客户端,即使主指针更改,该副本也将保持不变。这可能会也可能不可接受,具体取决于您的要求的时间紧迫程度。这应该足以避免任何未定义的行为——垃圾收集器将确保指针始终保持有效,即使您的程序不再使用所指向的内存。另一种方法是只从一个 go 例程进行指针访问,并使用通道命令 go 例程执行某些操作。这将被认为是更惯用的 go,但可能不完全适合您的应用程序。更新这是一个示例,展示了如何使用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))}

MYYA

由于规范没有指定,你应该假设它不是。即使它目前是原子的,它也有可能在不违反规范的情况下进行更改。

叮当猫咪

除了尼克的回答之外,从 Go 1.4 开始,还有atomic.Value类型。它Store(interface)和Load() interface方法负责unsafe.Pointer转换。简单的例子:package mainimport (    "sync/atomic")type stats struct{}type myType struct {    stats atomic.Value}func main() {    var t myType        s := new(stats)        t.stats.Store(s)        s = t.stats.Load().(*stats)}或者来自Go playground文档的更扩展示例。
随时随地看视频慕课网APP

相关分类

Go
我要回答