如何原子商店&在golang中加载一个接口?

时间:2017-12-11 10:34:58

标签: go atomic

我想写一些这样的代码:

 classThreads.c: In member function ‘void A::myFunc()’:
classThreads.c:40:42: error: cannot convert ‘A::func’ from type ‘void* (A::)(void*)’ to type ‘void* (*)(void*)’
       pthread_create(&tid, NULL, func, &p);

似乎我可以在原子包中使用 LoadUintptr(addr * uintptr)(val uintptr) StoreUintptr(addr * uintptr,val uintptr)来实现此目的,但我不知道如何在 uintptr unsafe.Pointer interface {} 之间进行转换。

如果我这样做:

var myValue interface{}

func GetMyValue() interface{} {
    return atomic.Load(myValue)
}

func StoreMyValue(newValue interface{}) {
    atomic.Store(myValue, newValue)
}

V 将始终为1

3 个答案:

答案 0 :(得分:3)

如果我没弄错,你想要atomic Value。您可以使用它以原子方式存储和获取值(签名为interface{}但您应该将相同的类型放入其中)。它会像你想做的那样做一些不安全的指针。

来自docs的示例:

var config Value // holds current server configuration
// Create initial config value and store into config.
config.Store(loadConfig())
go func() {
        // Reload config every 10 seconds
        // and update config value with the new version.
        for {
                time.Sleep(10 * time.Second)
                config.Store(loadConfig())
        }
}()
// Create worker goroutines that handle incoming requests
// using the latest config value.
for i := 0; i < 10; i++ {
        go func() {
                for r := range requests() {
                        c := config.Load()
                        // Handle request r using config c.
                        _, _ = r, c
                }
        }()
}

答案 1 :(得分:0)

你不能这样做。

您必须使用互斥锁保护商店/负载。 接口的内部表示不是由语言指定的,并且可能(是)大到由包原子处理。

答案 2 :(得分:0)

以下是使用atomic.StorePointeratomic.LoadPointer的方式(基于您的示例):

package main

import (
    "fmt"
    "sync/atomic"
    "unsafe"
)

var addr unsafe.Pointer

func GetMyValue() *interface{} {
    return (*interface{})(atomic.LoadPointer(&addr))
}

func StoreMyValue(newValue *interface{}) {
    atomic.StorePointer(&addr, unsafe.Pointer(newValue))
}

func main() {
    var i interface{}
    i = 1
    StoreMyValue(&i)
    fmt.Println("before:", *GetMyValue())
    i = 2
    StoreMyValue(&i)
    fmt.Println("after", *GetMyValue())
}

游乐场link

请注意,这不会使您的对象成为线程安全的。只有指针以原子方式存储/加载。另外,我会尽量避免使用interface{}并且更喜欢具体的类型。