zoukankan      html  css  js  c++  java
  • Golang之并发资源竞争(读写锁)

    前面的有篇文章在讲资源竞争的时候,提到了互斥锁。互斥锁的根本就是当一个goroutine访问的时候,其他goroutine都不能访问,这样肯定保证了资源的同步,避免了竞争,不过也降低了性能。

    仔细剖析我们的场景,当我们读取一个数据的时候,如果这个数据永远不会被修改,那么其实是不存在资源竞争的问题的。因为数据是不变的,不管怎么读取,多少goroutine同时读取,都是可以的。

    所以其实读取并不是问题,问题主要是修改。修改的数据要同步,这样其他goroutine才可以感知到。所以真正的互斥应该是读取和修改、修改和修改之间,读取和读取是没有互斥操作的。

    所以这就延伸出来另外一种锁,叫做读写锁。

    读写锁可以让多个读操作同时并发,同时读取,但是对于写操作是完全互斥的。也就是说,当一个goroutine进行写操作的时候,其他goroutine既不能进行读操作,也不能进行写操作。

    package main
    
    import (
        "sync"
        "fmt"
        "math/rand"
    )
    var count int
    var wg sync.WaitGroup
    var rw sync.RWMutex
    
    func main() {
        wg.Add(10)
        for i:=0;i<5;i++ {
            go read(i)
        }
        for i:=0;i<5;i++ {
            go write(i)
        }
        wg.Wait()
    }
    
    func read(n int) {
        rw.RLock()
        fmt.Printf("读goroutine %d 正在读取...
    ",n)
        v := count
        fmt.Printf("读goroutine %d 读取结束,值为:%d
    ", n,v)
        wg.Done()
        rw.RUnlock()
    }
    
    func write(n int) {
        rw.Lock()
        fmt.Printf("写goroutine %d 正在写入...
    ",n)
        v := rand.Intn(1000)
        count = v
        fmt.Printf("写goroutine %d 写入结束,新值为:%d
    ", n,v)
        wg.Done()
        rw.Unlock()
    }

    我们在read里使用读锁,也就是RLock和RUnlock,写锁的方法名和我们平时使用的一样,是Lock和Unlock。这样,我们就使用了读写锁,可以并发地读,但是同时只能有一个写,并且写的时候不能进行读操作。现在我们再运行代码,可以从输出的数据看到,可以读到新值了。

    我们同时也可以使用go build -race检测,也没有竞争提示了。

  • 相关阅读:
    一二线城市知名 IT 互联网公司名单!
    分布式理论- CAP定理
    Linux中安装ActiveMQ完整教程
    Nginx安装-配置负载均衡
    基于SpringBoot+Vue在线学习系统实现
    序列化多个对象和反序列化遍历一个文件中的所有对象原理讲解
    从源码看懂HashMap
    Mac在已有jdk1.8的环境下安装jdk1.6
    mac通过Parallels Desktop虚拟机实现共享windows独有软件提供的特殊网络
    算法题汇总
  • 原文地址:https://www.cnblogs.com/liuzhongchao/p/9372289.html
Copyright © 2011-2022 走看看