concurrency - 在 Go 中分配一个指针是原子的吗?

标签 concurrency go atomic

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

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

最佳答案

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

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

使用 mutex 是 OK 的风格——你可以定义一个函数来返回当前指针并非常容易地锁定,例如类似的东西

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 例程进行指针访问,并使用 channel 命令该 go 例程执行操作。这将被认为是更惯用的 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/41531337/

相关文章:

java - java中默认可以并发执行实例方法吗?

scala - 为什么 Akka Actor 的默认行为是一个接一个地处理消息?

sql - 将枚举值保存到数据库

struct - 多个结构开关?

c++ - 我们如何强制变量共享?

java - 为什么 JMM 会产生 (0, 0),即使它被认为是禁止的结果

javascript - 异步函数中并发 Promise 的顺序如何工作?

google-app-engine - 带有光标的Google App Engine数据存储区查询不会迭代所有项

java - 为什么像获取和添加这样的原子操作会返回被更改变量的旧值?

c++ - 为什么自由函数和成员函数都存在用于比较和交换操作?