总结
Mutex互斥锁
- 适用于读写次数没有明显的区别
- 只允许只有一个读或者写
RWMutex读写锁
- 适用于读多写少
- 同时只能有一个 goroutine 能够获得写锁定;
- 同时可以有任意多个 gorouinte 获得读锁定;
- 同时只能存在写锁定或读锁定(读和写互斥)。
注意:同一线程不要多次加锁和解锁
一、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 就会引发一个运行时错误
package main
import (
"fmt"
"sync"
"time"
)
func main() {
var l sync.RWMutex
var ch = make(chan struct{}, 3)
go func() {
l.Lock()
defer l.Unlock()
fmt.Println("写锁定")
time.Sleep(time.Second * 2)
fmt.Println("马上解除写锁定")
ch <- struct{}{}
}()
time.Sleep(time.Millisecond)
go func() {
l.Lock()
defer l.Unlock()
fmt.Println("获取读锁")
time.Sleep(time.Second * 1)
ch <- struct{}{}
}()
time.Sleep(time.Millisecond)
go func() {
l.RLock()
defer l.RUnlock()
fmt.Println("获取读锁")
ch <- struct{}{}
}()
for i := 0; i < 3; i++ {
<- ch
}
}