在 Go 中分配指针是原子的吗?
我需要在锁中分配一个指针吗?假设我只想将指针分配给 nil,并希望其他线程能够看到它。我知道在 Java 中我们可以为此使用 volatile,但 Go 中没有 volatile。
最佳答案
在 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()
}
这些函数将指针的副本返回给它们的客户端,即使主指针发生更改,该副本也将保持不变。这可能会也可能不会接受,具体取决于您的要求对时间的要求。避免任何未定义的行为就足够了——垃圾收集器将确保指针始终保持有效,即使您的程序不再使用指向的内存。
另一种方法是仅从一个 goroutine 进行指针访问,并使用 channel 来命令 goroutine 执行操作。这将被认为是更惯用的 go,但可能不完全适合您的应用程序。
更新
Here is an example展示如何使用 atomic.SetPointer
。由于使用了unsafe.Pointer
,它相当难看。但是 unsafe.Pointer
将 compile 强制转换为空,因此运行时成本很小。
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))
}
关于concurrency - 在 Go 中分配指针是原子的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21447463/