RWMutex
读写锁相关的介绍使用
1. 读写锁的定义
涉及到俩个角色:读者和写者。
读者只读数据,写者修改它。当写者访问操作数据时,其他任何线程(读者或写者)都无法共享此数据的访问权限。
当写者释放数据时,多个读者同时读取该数据时可以正常访问。
读锁:只在写锁被锁定时,读锁才会起作用
写锁:会锁定写锁和读锁锁定的所有区域
2. 读写锁的使用
package main
import (
"fmt"
"sync"
"time"
)
type Stock struct {
good map[int]int
rw sync.RWMutex
}
var wg sync.WaitGroup
// 获取当个商品对应的库存
func (s *Stock)Get(k int) {
s.rw.RLock()
defer func() {
s.rw.RUnlock()
wg.Done()
}()
time.Sleep(time.Second * 5)
fmt.Println("locker is ", s.rw.RLocker() ,k," val reading ",s.good[k], " time: " ,time.Now().UnixNano())
}
func (s *Stock)Set(k,v int) {
s.rw.Lock()
defer func() {
wg.Done()
}()
s.good[k] = v
s.rw.Unlock()
fmt.Println(k," is writing ",v, " time: " ,time.Now().Unix())
}
func main() {
stock := Stock {
good : make(map[int]int,10),
}
wg.Add(30)
for i := 1 ; i<= 10 ; i++ {
go stock.Set(i,100)
}
for i := 1 ; i<= 10 ; i++ {
go stock.Get(i)
go stock.Get(i)
}
wg.Wait()
}
不加锁的情况下打印:
fatal error: concurrent map writes
参考文章:https://blog.csdn.net/simatongming/article/details/79075820
我们使用命令
go run main.go --race
打印结果:
fatal error: 4 is writing 100 time: 1548748976692000300
concurrent map writes2 is writing 100 time: 1548748976692000300
6 is writing 100 time: 1548748976692000300
加锁打印结果:
2 is writing 100 time: 1548751973
3 is writing 100 time: 1548751973
6 is writing 100 time: 1548751973
4 is writing 100 time: 1548751973
5 is writing 100 time: 1548751973
8 is writing 100 time: 1548751973
7 is writing 100 time: 1548751973
9 is writing 100 time: 1548751973
10 is writing 100 time: 1548751973
1 is writing 100 time: 1548751973
locker is &{{0 0} 0 0 20 0} 10 val reading 100 time: 1548751978371000300
locker is &{{0 0} 0 0 20 0} 1 val reading 100 time: 1548751978371000300
locker is &{{0 0} 0 0 20 0} 6 val reading 100 time: 1548751978371000300
locker is &{{0 0} 0 0 20 0} 1 val reading 100 time: 1548751978371000300
locker is &{{0 0} 0 0 20 0} 5 val reading 100 time: 1548751978371000300
locker is &{{0 0} 0 0 20 0} 8 val reading 100 time: 1548751978371000300
locker is &{{0 0} 0 0 20 0} 5 val reading 100 time: 1548751978371000300
locker is &{{0 0} 0 0 20 0} 2 val reading 100 time: 1548751978371000300
locker is &{{0 0} 0 0 20 0} 3 val reading 100 time: 1548751978371000300
locker is &{{0 0} 0 0 20 0} 2 val reading 100 time: 1548751978371000300
locker is &{{0 0} 0 0 20 0} 10 val reading 100 time: 1548751978371000300
locker is &{{0 0} 0 0 20 0} 8 val reading 100 time: 1548751978371000300
locker is &{{0 0} 0 0 20 0} 7 val reading 100 time: 1548751978371000300
locker is &{{0 0} 0 0 20 0} 4 val reading 100 time: 1548751978371000300
locker is &{{0 0} 0 0 20 0} 9 val reading 100 time: 1548751978371000300
locker is &{{0 0} 0 0 20 0} 7 val reading 100 time: 1548751978371000300
locker is &{{0 0} 0 0 20 0} 4 val reading 100 time: 1548751978371000300
locker is &{{0 0} 0 0 20 0} 9 val reading 100 time: 1548751978371000300
locker is &{{0 0} 0 0 20 0} 3 val reading 100 time: 1548751978371000300
locker is &{{0 0} 0 0 20 0} 6 val reading 100 time: 1548751978371000300
可以看到,我们虽然对读锁加了阻塞,但是所有的good数据都还是同时过了5s读出来了,只有写操作,才会
阻塞读,这样我们就能避免读到脏数据
更多更详细的解释可以参看这篇文章 : https://medium.com/golangspec/sync-rwmutex-ca6c6c3208a0