• Mutex和RWMutex


    Golang 中的有两种锁,为 sync.Mutex 和 sync.RWMutex

    • sync.Mutex 的锁只有一种锁:Lock(),它是绝对锁,也称互斥锁,同一时间只能有一个锁。
    • sync.RWMutex 叫读写锁,它有两种锁: RLock() 和 Lock()
      • RLock() 叫读锁。它不是绝对锁,可以有多个读者同时获取此锁(调用 mu.RLock)。
      • Lock() 叫写锁,它是个绝对锁,就是说,如果一旦某人拿到了这个锁,别人就不能再获取此锁了

    1 Mutex是互斥锁

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

    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) {
        // 读锁是RLock(),
        rw.RLock()
        fmt.Printf("读goroutine %d 正在读取...
    ",n)
        v := count
        fmt.Printf("读goroutine %d 读取结束,值为:%d
    ", n,v)
        wg.Done()
        rw.RUnlock()
    }
    func write(n int) {
        // 写锁是Lock()
        rw.Lock()
        fmt.Printf("写goroutine %d 正在写入...
    ",n)
        v := rand.Intn(1000)
        count = v
        fmt.Printf("写goroutine %d 写入结束,新值为:%d
    ", n,v)
        wg.Done()
        rw.Unlock()
    }
    View Code

    map由于是非线程安全的,可以自己通过对map对象加锁来实现线程安全,具体操作是给新构造的map对象添加增删改查的方法,其中除了查添加读锁,其余的都是写锁,进而实现了线程安全,

    // 安全的Map
    type SynchronizedMap struct {
       rw *sync.RWMutex
       data map[interface{}]interface{}
    }
    // 存储操作
    func (sm *SynchronizedMap) Put(k,v interface{}){
       sm.rw.Lock()
       defer sm.rw.Unlock()
    
       sm.data[k]=v
    }
    // 获取操作  只有这个加的是读锁,
    func (sm *SynchronizedMap) Get(k interface{}) interface{}{
       sm.rw.RLock()
       defer sm.rw.RUnlock()
    
       return sm.data[k]
    }
    // 删除操作
    func (sm *SynchronizedMap) Delete(k interface{}) {
       sm.rw.Lock()
       defer sm.rw.Unlock()
    
       delete(sm.data,k)
    }
    // 遍历Map,并且把遍历的值给回调函数,可以让调用者控制做任何事情
    func (sm *SynchronizedMap) Each(cb func (interface{},interface{})){
       sm.rw.RLock()
       defer sm.rw.RUnlock()
       for k, v := range sm.data {
           cb(k,v)
       }
    }
    // 生成初始化一个SynchronizedMap
    func NewSynchronizedMap() *SynchronizedMap{
       return &SynchronizedMap{
           rw:new(sync.RWMutex),
           data:make(map[interface{}]interface{}),
       }
    }
    View Code

    参考:https://mp.weixin.qq.com/s/wyezW1swNlDkXi4V-ABa-w

    http://www.coder55.com/article/27284

  • 相关阅读:
    【Golang】 关于Go 并发之三种线程安全的 map
    Halodoc使用 Apache Hudi 构建 Lakehouse的关键经验
    Logstash优化吞吐率
    ES集群状态yellow修复
    ES集群状态red修复
    vxetable 导出Excel 超过100条,自定义模板template替换失效
    [转]使用minio搭建自己的文件存储服务(新版和旧版)
    [转]vue 预览pdf,txt
    windows7 使用nvs升级降级node.js版本
    新建Token来访问K8S apiserver
  • 原文地址:https://www.cnblogs.com/xxswkl/p/14248560.html
Copyright © 2020-2023  润新知