这是 Go 代码
package main
import (
"fmt"
"math/rand"
)
type MyType struct {
}
func main() {
chanAdd := make(chan *MyType, 1)
chanRemove := make(chan *MyType, 1)
chanGive := make(chan *any, 1)
foundCount, notFoundCount := .0, .0
total := .0
percent := .0
go func() {
localStore := make(map[*MyType]bool)
for {
<-chanGive
for i := 0; i < 10; i++ {
item := new(MyType)
localStore[item] = true
chanAdd <- item
}
for item, _ := range localStore {
if rand.Intn(10) > 5 {
chanRemove <- item
delete(localStore, item)
}
}
}
}()
store := make(map[*MyType]bool)
for {
select {
case item := <-chanAdd:
store[item] = true
case item := <-chanRemove:
total++
if _, found := store[item]; found {
delete(store, item)
foundCount++
} else {
notFoundCount++
}
default:
if len(chanGive) == 0 {
chanGive <- new(any)
}
}
if total > 0 {
percent = foundCount / total * 100
}
fmt.Printf("\rFound: %f%%", percent)
}
}
我们有两个存储指针的映射。一种是 go 例程本地的,另一种仅在主进程中使用。 go 例程通过一个通道发送要存储的指针,并在另一个通道中发送要删除的指针。
主进程检查之前是否已添加了要求删除的指针。然后显示实际找到并删除的指针的百分比。
此代码输出 100% 成功。
但是,如果您更改通道大小,例如 100:
chanAdd := make(chan *MyType, 100)
chanRemove := make(chan *MyType, 100)
然后百分比下降到~90%。 当然,这是一个简化的示例,但我面临着一个更复杂的代码的实际问题。
我搜索了指针在通过通道时到底发生了什么。但我找不到答案。
go run -race
似乎没有检测到竞争条件。我可能错了?
写这个简化的例子来发布这个问题对我帮助很大! 事实上,在我给出的示例中,对于较大的通道,有时代码会尝试删除尚未添加到列表中的指针。