当我运行我的代码时,会出现种族状况。它是并发安全存储的简单实现。当我将get()方法中的接收者更改为(p *storageType)时,Race条件就消失了。我很困惑。我需要一个能向我解释这种行为的人。
package main
type storageType struct {
fc chan func()
value int
}
func newStorage() *storageType {
p := storageType{
fc: make(chan func()),
}
go p.run()
return &p
}
func (p storageType) run() {
for {
(<-p.fc)()
}
}
func (p *storageType) set(s int) {
p.fc <- func() {
p.value = s
}
}
func (p storageType) get() int {
res := make(chan int)
p.fc <- func() {
res <- p.value
}
return <-res
}
func main() {
storage := newStorage()
for i := 0; i < 1000; i++ {
go storage.set(i)
go storage.get()
}
}发布于 2021-04-22 15:21:17
在main()中,storage变量的类型为*storageType。如果storageType.Get()有值接收者,那么storage.get()的意思是(*storage).get()。
get()调用以storageType作为累赘,因此必须取消storage指针变量的引用,以创建副本(将用作接收方值)。此复制意味着必须读取指定的storageType结构的值。但此读取与run()方法不同步,该方法读取和写入结构(其value字段)。
如果将get()的接收方更改为指针(类型为*storageType),则接收器将再次为副本,但这一次它将是指针的副本,而不是指向的结构。因此不会发生结构的不同步读取。
见可能的副本:Why does the method of a struct that does not read/write its contents still cause a race case?
发布于 2021-04-22 15:21:23
第一个:您的main函数不会等待所有的goroutines完成。当main回来的时候,所有的猩猩都会被迫返回。
查看使用sync.WaitGroup
https://stackoverflow.com/questions/67216060
复制相似问题