总结
    Mutex互斥锁

    • 适用于读写次数没有明显的区别
    • 只允许只有一个读或者写

    RWMutex读写锁

    • 适用于读多写少
    • 同时只能有一个 goroutine 能够获得写锁定;
    • 同时可以有任意多个 gorouinte 获得读锁定;
    • 同时只能存在写锁定或读锁定(读和写互斥)。

    注意:同一线程不要多次加锁和解锁
    image.png
    一、Mutex互斥锁
    Lock()加锁,Unlock()解锁,使用Lock()加锁后,便不能再次对其进行加锁,直到利用Unlock()解锁对其解锁后,才能再次加锁.

    适用于读写不确定场景,即读写次数没有明显的区别,并且只允许只有一个读或者写的场景,所以该锁叶叫做全局锁.
    注意:
    1.既同一个协程同一时刻只能加一个锁,不同线程之间的锁没有限制,多次加锁会panic
    2.已经锁定的Mutex并不与特定的goroutine相关联,这样可以利用一个goroutine对其加锁,再利用其他goroutine对其解锁.

    二、RWMutex读写锁
    1.写锁
    func (rw RWMutex) Lock()  写锁,如果在添加写锁之前已经有其他的读锁和写锁,则lock就会阻塞直到该锁可用,为确保该锁最终可用,已阻塞的 Lock 调用会从获得的锁中排除新的读取器,即写锁权限高于读锁,有写锁时优先进行写锁定
    func (rw
    RWMutex) Unlock() 写锁解锁,如果没有进行写锁定,则就会引起一个运行时错误.

    2.读锁
    func (rw RWMutex) RLock() 读锁,当有写锁时,无法加载读锁,当只有读锁或者没有锁时,可以加载读锁,读锁可以加载多个,所以适用于"读多写少"的场景

    func (rw
    RWMutex)RUnlock() 读锁解锁,RUnlock 撤销单次 RLock 调用,它对于其它同时存在的读取器则没有效果。若 rw 并没有为读取而锁定,调用 RUnlock 就会引发一个运行时错误

    1. package main
    2. import (
    3. "fmt"
    4. "sync"
    5. "time"
    6. )
    7. func main() {
    8. var l sync.RWMutex
    9. var ch = make(chan struct{}, 3)
    10. go func() {
    11. l.Lock()
    12. defer l.Unlock()
    13. fmt.Println("写锁定")
    14. time.Sleep(time.Second * 2)
    15. fmt.Println("马上解除写锁定")
    16. ch <- struct{}{}
    17. }()
    18. time.Sleep(time.Millisecond)
    19. go func() {
    20. l.Lock()
    21. defer l.Unlock()
    22. fmt.Println("获取读锁")
    23. time.Sleep(time.Second * 1)
    24. ch <- struct{}{}
    25. }()
    26. time.Sleep(time.Millisecond)
    27. go func() {
    28. l.RLock()
    29. defer l.RUnlock()
    30. fmt.Println("获取读锁")
    31. ch <- struct{}{}
    32. }()
    33. for i := 0; i < 3; i++ {
    34. <- ch
    35. }
    36. }