原创分享 sync.RWMutex 功能的测试

wanna · 2020年09月15日 · 最后由 wanna 回复于 2020年09月20日 · 1848 次阅读
本帖已被设为精华帖!

RWMutex 里共四个方法

func (rw *RWMutex) Lock() // 写锁
func (rw *RWMutex) Unlock() // 写解锁

func (rw *RWMutex) RLock() // 读锁
func (rw *RWMutex) RUnlock() // 读解锁

这里要着重理解下

  1. 读锁不互斥(可以多个一起读)
  2. 写锁互斥(只能有一个在写入)
  3. 有读不可写,有写不可读(读写不能同时进行)

我使用了两个方法验证加读写锁后的安全其中
fun rwMutex(i int) 使用了 RWMutex 锁,开协程并发的累加到 10000,同时开协程累减到 10000,最终得到的值为 0,证明加锁后是独写安全的
fun rwWithoutMutex(i int) 没有使用了 RWMutex 锁,同上一方法先同时累加累减,得到结果不为预期值 0,所以独写不安全

代码如下

type info struct {
    sync.RWMutex
    data int
}

func rwMutex(count int)  {
    c := make(chan struct{},count * 3)
    l := info{data:0}
    for i := 0; i < count; i++ {
        go func() {
            l.RLock()
            d := l.data
            fmt.Printf("我读取到了data,值为:%d\n",d)
            l.RUnlock()
            c <- struct{}{}
        }()
    }
    for i := 0; i < count; i++ {
        go func(i int) {
            l.Lock()
            l.data += i
            fmt.Printf("我把data的值加了%d变成了%d\n",i,l.data)
            l.Unlock()
            c <- struct{}{}
        }(i)
    }
    for i := 0; i < count; i++ {
        go func(i int) {
            l.Lock()
            l.data -= i
            fmt.Printf("我把data的值减了%d变成了%d\n",i,l.data)
            l.Unlock()
            c <- struct{}{}
        }(i)
    }
    for i := 0; i < count * 3; i++ {
        <-c
    }
    fmt.Printf("data的最终结果应该为0,实际结果为:%d",l.data)
}

func rwWithoutMutex(count int)  {
    c := make(chan struct{},count * 3)
    l := 0
    for i := 0; i < count; i++ {
        go func() {
            fmt.Printf("我读取到了data,值为:%d\n",l)
            c <- struct{}{}
        }()
    }
    for i := 0; i < count; i++ {
        go func(i int) {
            l += i
            fmt.Printf("我把data的值加了%d变成了%d\n",i,l)
            c <- struct{}{}
        }(i)
    }
    for i := 0; i < count; i++ {
        go func(i int) {
            l -= i
            fmt.Printf("我把data的值减了%d变成了%d\n",i,l)
            c <- struct{}{}
        }(i)
    }
    for i := 0; i < count * 3; i++ {
        <-c
    }
    fmt.Printf("不安全读写时data的最终结果应该为0,实际结果为:%d",l)
}

调用 rwMutex(10000) 得到结果

... ...
我把data的值减了9869变成了88935
我把data的值减了9866变成了79069
我把data的值减了9867变成了69202
我把data的值减了9864变成了59338
我把data的值减了9929变成了49409
我把data的值减了9868变成了39541
我把data的值减了9928变成了29613
我把data的值减了9871变成了19742
我把data的值减了9870变成了9872
我把data的值减了9872变成了0
data的最终结果应该为0,实际结果为:0

调用 rwWithoutMutex(10000) 得到结果

... ...
我读取到了data,值为:0
我读取到了data,值为:0
我读取到了data,值为:0
我把data的值加了175变成了-30536
我把data的值加了1410变成了-30536
我读取到了data,值为:0
我把data的值加了811变成了-356884
我读取到了data,值为:0
我读取到了data,值为:0
不安全读写时data的最终结果应该为0,实际结果为:-30536
更多原创文章干货分享,请关注公众号
  • 加微信实战群请加微信(注明:实战群):gocnio
astaxie 将本帖设为了精华贴 09月15日 23:31

😁 可以玩玩各种死锁场景

yulibaozi GoCN 每日新闻(2020-09-18) 中提及了此贴 09月18日 21:12
cch123 回复

有空时一个一个的玩明白

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册