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))
}
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文档的更扩展示例。
- 3 回答
- 0 关注
- 357 浏览
添加回答
举报