1.互斥锁

goroutinesyncMutex
var x int64
var wg sync.WaitGroup
var lock sync.Mutex

func add() {
	for i := 0; i < 5000; i++ {
		lock.Lock() // 加锁
		x = x + 1
		lock.Unlock() // 解锁
	}
	wg.Done()
}
func main() {
	wg.Add(2)
	go add()
	go add()
	wg.Wait()
	fmt.Println(x)
}

结果永远是10000。 对公共资源操作时,应该加锁

goroutinegoroutinegoroutinegoroutine

模拟读多写少的一个场景

var (
   x = 0
   wg sync.WaitGroup
   lock sync.Mutex
)

func  read ()  {
   defer  wg.Done()
   lock.Lock()
   fmt.Println(x)
   time.Sleep(time.Millisecond)         读需要1毫秒
   lock.Unlock()
}
func write()  {
   defer  wg.Done()
   lock.Lock()
   x ++
   lock.Unlock()
   time.Sleep(time.Millisecond * 5)    写需要5毫秒
}
func main()  {
   start := time.Now()
   for i:= 0; i<10 ; i++  {
      go write()
      wg.Add(1)
   }
   for i:= 0; i<1000 ; i++  {
      go read()
      wg.Add(1)
   }

   wg.Wait()
   fmt.Println(time.Since(start))    15.516195s

}

互斥锁,在读的时候,也会阻塞下一个读线程,这样效率很低。

2.读写互斥锁

普通锁是 sync.Mutex
读写锁是 sync.RWMutex

syncRWMutex
goroutinegoroutinegoroutine

RWMutex提供了四个方法:

func (*RWMutex) Lock // 写锁定

func (*RWMutex) Unlock // 写解锁

func (*RWMutex) RLock // 读锁定

func (*RWMutex) RUnlock // 读解锁

读写锁示例:

var (
   x = 0
   wg sync.WaitGroup
   lock sync.RWMutex
)

func  read ()  {
   defer  wg.Done()
   lock.RLock()                         加读锁
   fmt.Println(x)
   time.Sleep(time.Millisecond)
   lock.RUnlock()						解读锁
}
func write()  {
   defer  wg.Done()                     加写锁
   lock.Lock()
   x ++
   lock.Unlock()						解写锁
   time.Sleep(time.Millisecond * 5)
}
func main()  {
   start := time.Now()
   for i:= 0; i<10 ; i++  {
      go write()
      wg.Add(1)
   }
   for i:= 0; i<1000 ; i++  {
      go read()
      wg.Add(1)
   }

   wg.Wait()
   fmt.Println(time.Since(start))                        20.0658ms,速度和互斥锁差别非常大

}

需要注意的是读写锁非常适合读多写少的场景,如果读和写的操作差别不大,读写锁的优势就发挥不出来。