go并发编程之六(sync之读写锁RWMutex)

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

猜你喜欢

转载自blog.csdn.net/wujiangwei567/article/details/86692859
今日推荐