为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
慕尼黑8549860 2021-07-05 12:14:50
在 Go 中分配指针是原子的吗?我需要在锁中分配一个指针吗?假设我只想将指针分配给 nil,并希望其他线程能够看到它。我知道在 Java 中我们可以为此使用 volatile,但在 Go 中没有 volatile。
查看完整描述

3 回答

?
翻过高山走不出你

TA贡献1875条经验 获得超3个赞

在 go 中唯一保证原子性的是sync.atomic中的操作。


因此,如果您想确定您要么需要锁定,例如sync.Mutex,要么使用原子原语之一。我不建议使用原子原语,因为你必须在任何使用指针的地方使用它们,而且它们很难正确使用。


使用互斥锁是可以的 - 您可以定义一个函数来非常容易地通过锁定返回当前指针,例如类似的东西


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()

}

这些函数将指针的副本返回给它们的客户端,即使主指针更改,该副本也将保持不变。这可能会也可能不可接受,具体取决于您的要求的时间紧迫程度。这应该足以避免任何未定义的行为——垃圾收集器将确保指针始终保持有效,即使您的程序不再使用所指向的内存。


另一种方法是只从一个 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))


}


查看完整回答
反对 回复 2021-07-19
?
MYYA

TA贡献1868条经验 获得超4个赞

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


查看完整回答
反对 回复 2021-07-19
?
叮当猫咪

TA贡献1776条经验 获得超12个赞

除了尼克的回答之外,从 Go 1.4 开始,还有atomic.Value类型。它Store(interface)和Load() interface方法负责unsafe.Pointer转换。


简单的例子:


package main


import (

    "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文档的更扩展示例。


查看完整回答
反对 回复 2021-07-19
  • 3 回答
  • 0 关注
  • 357 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信