How to use Load and Store of atomic in golang

huangapple go评论82阅读模式
英文:

How to use Load and Store of atomic in golang

问题

以下是用于测试使用atomic.Value对结构体B的写入和读取的代码片段,但是我遇到了一些指示无效指针访问的错误。那么我应该怎么做?有什么惯用的做法吗?

type A struct {
    numMap map[string]int
}

type B struct {
    numMap map[string]*A
}

var store atomic.Value

var chanA chan bool = make(chan bool, 100)
var chanB chan bool = make(chan bool, 100)

var b *B = &B{}

func fetchB() {
    for i := 0; i < 10000; i++ {
        c := store.Load().(*B)
        for k, v := range c.numMap {
            fmt.Println(k, v)
            for k2, v2 := range v.numMap {
                fmt.Println(k2, v2)
            }
        }
    }
    chanA <- true
}

func writeB() {
    for i := 0; i < 10000; i++ {
        a := new(A)
        a.numMap = make(map[string]int)
        a.numMap["AMap"] = i
        b.numMap = make(map[string]*A)
        b.numMap["str"] = a
        b.numMap["strA"] = a
        delete(b.numMap, "str")
        delete(b.numMap["strA"].numMap, "AMap")
        store.Store(b)
    }
    chanB <- true
}

func main() {
    store.Store(b)
    for i := 0; i < 100; i++ {
        go writeB()
        go fetchB()
    }
    for i := 0; i < 100; i++ {
        <-chanA
        <-chanB
    }
}

对于第一个问题,如果我注释掉b := store.Load().(B),错误就会出现;如果我保留它可见,错误就会消失。那么为什么会发生这种情况?

我得到的错误信息类似于:

panic: sync/atomic: store of inconsistently typed value into Value

goroutine 5 [running]: sync/atomic.(*Value).Store(0x597310, 0x4b7f40, 0x597198)
    /usr/local/go/src/sync/atomic/value.go:76 +0x1e9 main.writeB()
    /home/bzhang/devCode/common/src/go/src/audience_service/test.go:47 +0x2cc created by main.main
    /home/bzhang/devCode/common/src/go/src/audience_service/test.go:54 +0x71

goroutine 1 [chan receive]: main.main()
    /home/bzhang/devCode/common/src/go/src/audience_service/test.go:59 +0xf3

goroutine 6 [runnable]: main.fetchB()
    /home/bzhang/devCode/common/src/go/src/audience_service/test.go:23 created by main.main
    /home/bzhang/devCode/common/src/go/src/audience_service/test.go:55 +0x89

goroutine 7 [runnable]: main.writeB()
    /home/bzhang/devCode/common/src/go/src/audience_service/test.go:36 created by main.main
    /home/bzhang/devCode/common/src/go/src/audience_service/test.go:54 +0x71

goroutine 8 [runnable]: main.fetchB()
    /home/bzhang/devCode/common/src/go/src/audience_service/test.go:23 created by main.main
    /home/bzhang/devCode/common/src/go/src/audience_service/test.go:55 +0x89

goroutine 9 [runnable]: main.writeB()
    /home/bzhang/devCode/common/src/go/src/audience_service/test.go:36 created by main.main
    /home/bzhang/devCode/common/src/go/src/audience_service/test.go:54 +0x7

对于第一个问题,你可以尝试将c := store.Load().(B)更改为c := store.Load().(*B),因为store.Load()返回的是一个指向B类型的指针。这样可以解决类型不匹配的错误。

至于第二个问题,你可以使用atomic.Value来实现对结构体的原子读写操作。在这个例子中,我们使用store.Store(b)将结构体b存储到atomic.Value中,然后使用store.Load().(*B)来加载并获取结构体的副本。这样可以确保在读取和写入过程中的原子性。

希望这些解释对你有帮助!如果还有其他问题,请随时提问。

英文:

Here are the piece of code to test the mutual access of write and read of a struct B using atomic.Value, but I've got some error indicating invalid pointer access. So what should I do? And what is the idiomatic of doing this?

type A struct {
numMap map[string]int
}
type B struct {
numMap map[string]*A
}
var store atomic.Value
var chanA chan bool = make(chan bool, 100)
var chanB chan bool = make(chan bool, 100)
var b *B = &amp;B{}
func fetchB() {
for i := 0; i &lt; 10000; i++ {
c := store.Load().(B)
for k, v := range c.numMap {
fmt.Println(k, v)
for k2, v2 := range v.numMap {
fmt.Println(k2, v2)
}
}
}
chanA &lt;- true
}
func writeB() {
for i := 0; i &lt; 10000; i++ {
//b := store.Load().(B)
a := new(A)
a.numMap = make(map[string]int)
a.numMap[&quot;AMap&quot;] = i
b.numMap = make(map[string]*A)
b.numMap[&quot;str&quot;] = a
b.numMap[&quot;strA&quot;] = a
delete(b.numMap, &quot;str&quot;)
delete(b.numMap[&quot;strA&quot;].numMap, &quot;AMap&quot;)
store.Store(b)
}
chanB &lt;- true
}
func main() {
store.Store(*b)
for i := 0; i &lt; 100; i++ {
go writeB()
go fetchB()
}
for i := 0; i &lt; 100; i++ {
&lt;-chanA
&lt;-chanB
}
}

I'm sorry I've missed something in the first post of the question. If I comment b := store.Load().(B) the error raises, and it is gone if i leave it visible. So why would this happen?

the error I've got is something like this:

panic: sync/atomic: store of inconsistently typed value into Value
goroutine 5 [running]: sync/atomic.(*Value).Store(0x597310, 0x4b7f40, 0x597198)
/usr/local/go/src/sync/atomic/value.go:76 +0x1e9 main.writeB()
/home/bzhang/devCode/common/src/go/src/audience_service/test.go:47 +0x2cc created by main.main
/home/bzhang/devCode/common/src/go/src/audience_service/test.go:54 +0x71
goroutine 1 [chan receive]: main.main()
/home/bzhang/devCode/common/src/go/src/audience_service/test.go:59 +0xf3
goroutine 6 [runnable]: main.fetchB()
/home/bzhang/devCode/common/src/go/src/audience_service/test.go:23 created by main.main
/home/bzhang/devCode/common/src/go/src/audience_service/test.go:55 +0x89
goroutine 7 [runnable]: main.writeB()
/home/bzhang/devCode/common/src/go/src/audience_service/test.go:36 created by main.main
/home/bzhang/devCode/common/src/go/src/audience_service/test.go:54 +0x71
goroutine 8 [runnable]: main.fetchB()
/home/bzhang/devCode/common/src/go/src/audience_service/test.go:23 created by main.main
/home/bzhang/devCode/common/src/go/src/audience_service/test.go:55 +0x89
goroutine 9 [runnable]: main.writeB()
/home/bzhang/devCode/common/src/go/src/audience_service/test.go:36 created by main.main
/home/bzhang/devCode/common/src/go/src/audience_service/test.go:54 +0x7

答案1

得分: 1

当你注释掉b := store.Load().(B)这一行时,函数中使用的变量b是全局变量b,其类型为*B。当你执行store.Store(b)时,会出现错误,因为你试图将类型为*B的值存储到类型为B的存储器中。这就是为什么错误提到类型不一致。你可以将store.Store(b)改为store.Store(*b),这样代码就可以正常运行而不会出错。

英文:

When you comment out b := store.Load().(B) the variable b used in the function is the global b which is of type *B and when you do store.Store(b) you get the error because you are trying to store *B type value in the store which has value of type B. That's why the error talks about inconsistent type. You can change store.Store(b) to store.Store(*b) and the code will work without error.

huangapple
  • 本文由 发表于 2017年1月10日 15:21:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/41563290.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定