英文:
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 = &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++ {
//b := store.Load().(B)
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
}
}
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论