golang中map的三个结论:多协程同时只写入,会发生 concurrent map write 异常,必须加锁
多协程同时写入读取,写入加锁,读取不加,不会异常,只是不确保读取的数据是否脏
多协程同时只读取,加锁数据干净,不加锁数据可能脏

package main

import (
    "fmt"
    "runtime"
    "sync"
)

func main() {
    runtime.GOMAXPROCS(runtime.NumCPU())


    var m = make(map[string]*int,0)
    var l = & sync.RWMutex{}
    var a = 5
    m ["a"] = &a
    var wg = sync.WaitGroup{}
    for i:=0;i<10000;i++ {
        wg.Add(1)
        go func(wg *sync.WaitGroup, m *map[string]*int,l *sync.RWMutex) {
            defer wg.Done()

            writeM(m,l)
        }(&wg, &m, l)
    }
    for i:=0;i<10000;i++ {
        wg.Add(1)
        go func(wg *sync.WaitGroup, m *map[string]*int,l *sync.RWMutex) {
            defer wg.Done()

            readM(m,l)
        }(&wg, &m, l)
    }
    for i:=0;i<10000;i++ {
        wg.Add(1)
        go func(wg *sync.WaitGroup, m *map[string]*int,l *sync.RWMutex) {
            defer wg.Done()

            changeA(&a)
        }(&wg, &m, l)
    }

    wg.Wait()
}

func readM(m *map[string]*int,l *sync.RWMutex){
    l.RLock()
    defer l.RUnlock()
    a := (*m)["a"]
    fmt.Println(a)
}

func writeM(m *map[string]*int,l *sync.RWMutex) {
    l.Lock()
    defer l.Unlock()
    var tmp = 7
    (*m)["a"] = &tmp
}

func changeA(a *int){
    *a++
}



如代码所示,1万协程读,1万协程写,1万协程无锁修改其value指针对象的值,并不会因为造成读写崩溃。
map的读写场景:

var m map[string]*string
tmp := "3"
// 写
go func(){
 m["5"] = &tmp
 }
// 读
go func(){
_ = m["5"]
}()
// 此不属于写,是map安全的操作,无须加map 锁
*tmp = "4"