a. import(“sync”)b. 互斥锁, var mu sync.Mutex (只有一个释放之后,下一个才能进去)(sync.Mutex类型只有两个公开的指针方法:Lock、Unlock)c. 读写锁, var mu sync.RWMutex(读不锁,只有写才锁)d.原子锁,import "sync/atomic"
比如map,文件等被多个goroutine修改,则要做好锁。只读无需加锁
用go build -race xxx.go来编译,并运行二进制文件来查看竞争关系
互斥锁举例:
a := make(map[int]int, 5) a[0] = 10 fmt.Println(a) for i := 0; i < 2; i++ { go func(b map[int]int){ //设置互斥锁 lock.Lock() a[0] = rand.Intn(100) lock.Unlock() }(a) } //互斥锁不读还是写,都要设置才能确保不竞争 lock.Lock() fmt.Println(a) lock.Unlock()
读写锁(包括原子锁)举例:
package main import ( "sync" "fmt" "math/rand" "time" "sync/atomic" ) var rwLock sync.RWMutex func main() { var count int32 //读写锁 a := make(map[int]int, 5) a[0] = 10 fmt.Println(a) for i := 0; i < 2; i++ { go func(b map[int]int){ //写的锁是Lock rwLock.Lock() a[0] = rand.Intn(100) rwLock.Unlock() }(a) } for i := 0; i < 100; i++ { go func(b map[int]int){ //读的锁是RLock rwLock.RLock() fmt.Println(a) //原子锁引用赋值count,每次加一 atomic.AddInt32(&count, 1) rwLock.RUnlock() }(a) } time.Sleep(time.Second) //输出原子锁次数也要有固定写法 fmt.Println(atomic.LoadInt32(&count)) }