多个 goroutine 共用普通 map 时,把读和写都放在同一把锁的保护下。计数递增属于读改写,应在一次写锁内完成。

用结构体把 map 和锁绑在一起
将下面程序保存为 main.go。方法使用指针接收者。
package main
import (
"fmt"
"sync"
)
type Counts struct {
mu sync.RWMutex
values map[string]int
}
func (c *Counts) Inc(key string) {
c.mu.Lock()
defer c.mu.Unlock()
c.values[key]++
}
func (c *Counts) Get(key string) int {
c.mu.RLock()
defer c.mu.RUnlock()
return c.values[key]
}
func main() {
counts := &Counts{values: make(map[string]int)}
var done sync.WaitGroup
for i := 0; i <p><img src="https://img.php.cn/upload/image/109/573/622/1794560892323587.jpg?x-oss-process=image/resize,p_40" alt=""></p><p>map 初始化后通过方法访问。锁开始使用后,不要按值复制包含它的结构体。</p><h2>核对并发计数</h2><p>运行完整程序。</p><pre class="brush:php;toolbar:false;">go run main.go
# 8000
八个 goroutine 各递增一千次,结果应始终为 8000。
再用竞态检测运行一次
在本机支持的情况下执行。
go run -race main.go
正常情况下不会报告数据竞争。新增删除或遍历方法时,也要用同一把锁保护访问。










