在golang中分配指针原子?

Kod*_*oda 18 concurrency atomic go

将指针原子分配给go?

我需要在锁中指定一个指针吗?假设我只想将指针指向nil,并希望其他线程能够看到它.我知道在java中我们可以使用volatile.但是没有波动性.

谢谢.

Nic*_*ood 16

唯一保证是原子的东西是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()
}
Run Code Online (Sandbox Code Playgroud)

这些函数将指针的副本返回给它们的客户端,即使主指针被更改,它也将保持不变.根据您的要求的时间关键程度,这可能是也可能不可接受.它应该足以避免任何未定义的行为 - 垃圾收集器将确保指针始终保持有效,即使程序不再使用指向的内存.

另一种方法是仅从一个例程中执行指针访问,并使用通道来命令该例程执行操作.这将被认为是更惯用的,但可能不适合您的应用程序.

更新

这是一个显示如何使用的示例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))

}
Run Code Online (Sandbox Code Playgroud)

  • @ NickCraig-Wood在使用“ atomic.StorePointer”时,是否有必要使用“ atomic.ReadPointer”来读取它?还是可以正常进行非原子读取?“ atomic.StorePointer”中使用的存储屏障应阻止并发读取,因此在这种情况下使用“ atomic.ReadPointer”对我来说听起来毫无用处。那正确吗? (2认同)

Jer*_*all 6

由于规范没有规定你应该假设它不是.即使它目前处于原子状态,它也可能在不违反规范的情况下发生变化.