读写协程要用读写锁

106 阅读1分钟

由于互斥锁对于共享资源形成了独占,所以在代码上也就达到了一种严格的串行化执行
优点:可以控制住代码的执行步骤 缺点:让高并发的程序性能打了折扣

在实际开发中,根据应用场景会把所分为读锁写锁

读锁:会阻止别人的写,不会阻止别人的写
写锁:会阻止别人的写,也会阻止别人的读

如果把互斥锁换成适合应用场景的读写锁,那么一定会因为读锁达到一定数量级而产生性能提升
读写锁,从源代码的结构体里看,就可以发现,它是在互斥锁的基础上加计数器实现的
所以:在单独拿到一把锁的效率上来看,一定是互斥锁获取更快

package main

import (
   "fmt"
   "sync"
   "time"
)

var (
   x      int64
   wg     sync.WaitGroup
   lock   sync.Mutex
   rwlock sync.RWMutex
)

func write() {
   // lock.Lock()   // 加互斥锁
   rwlock.Lock() // 加写锁,写锁会阻止别人的写,也会阻止别人的读
   x = x + 1
   time.Sleep(10 * time.Millisecond) // 假设写操作耗时10毫秒
   rwlock.Unlock()                   // 解写锁
   // lock.Unlock()                     // 解互斥锁
   wg.Done()
}

func read() {
   // lock.Lock()                  // 加互斥锁
   rwlock.RLock()               // 加读锁,读锁会阻止别人的写,不会阻止别人的写
   time.Sleep(time.Millisecond) // 假设读操作耗时1毫秒
   rwlock.RUnlock()             // 解读锁
   // lock.Unlock()                // 解互斥锁
   wg.Done()
}

func main() {
   start := time.Now()
   for i := 0; i < 10; i++ {
      wg.Add(1)
      go write()
   }

   for i := 0; i < 1000; i++ {
      wg.Add(1)
      go read()
   }

   wg.Wait()
   end := time.Now()
   fmt.Println(end.Sub(start))
}

//明显对比出来:当读锁需求明显多于写锁需求时,读写锁的优势会在数量级上优于互斥锁
//使用互斥锁耗时:
//1.7243907s

//使用读写互斥锁:
//176.6876ms