Mutex:互斥锁
type Mutex struct {
// 包含隐藏或非导出字段
}
Mutex是一个互斥锁,可以创建为其他结构体的字段;零值为解锁状态。Mutex类型的锁和线程无关,可以由不同的线程加锁和解锁。
- 在一个 goroutine 获得 Mutex 后,其他 goroutine 只能等到这个 goroutine 释放该 Mutex
- 使用Lock()加锁后,便不能再次对其进行加锁,直到利用Unlock()解锁对其解锁后,才能再次加锁.
- 适用于读写不确定场景,即读写次数没有明显的区别,并且只允许只有一个读或者写的场景,所以该锁叶叫做全局锁
- 在同一个 goroutine 中的 Mutex 解锁之前再次进行加锁,会导致死锁
func (m *Mutex) Lock()
//Lock方法锁住m,如果m已经加锁,则阻塞直到m解锁。
func (m *Mutex) Unlock()
//Unlock方法解锁m,如果m未加锁会导致运行时错误。
//锁和线程无关,可以由不同的线程加锁和解锁。
示例代码:
加锁和解锁:
package main
import (
"fmt"
"sync"
)
func main() {
var L *sync.Mutex //互斥锁
L = new(sync.Mutex)
L.Lock() //加锁
defer L.Unlock() //解锁
fmt.Println("hello")
}
//结果:hello
在解锁之前加锁会导致死锁:
package main
import (
"fmt"
"sync"
)
func main() {
var L *sync.Mutex //互斥锁
L = new(sync.Mutex)
L.Lock() //加锁
//defer L.Unlock() //解锁
fmt.Println("hello")
L.Lock()//再次加锁
}
//结果:
//hello
//fatal error: all goroutines are asleep - deadlock!
RWMutex:读写锁,RWMutex 基于 Mutex 实现
type RWMutex struct {
// 包含隐藏或非导出字段
}
RWMutex是读写互斥锁。该锁可以被同时多个读取者持有或唯一个写入者持有。RWMutex可以创建为其他结构体的字段;零值为解锁状态。RWMutex类型的锁也和线程无关,可以由不同的线程加读取锁/写入和解读取锁/写入锁。
- 可以加多个读锁或者一个写锁
- 写锁权限高于读锁,有写锁时优先进行写锁定
- 读锁占用的情况下会阻止写,不会阻止读,多个 goroutine 可以同时获取读锁
- 写锁会阻止其他 goroutine(无论读和写)进来,整个锁由该 goroutine 独占
func (rw *RWMutex) Lock()
//Lock方法将rw锁定为写入状态,禁止其他线程读取或者写入。
func (rw *RWMutex) Unlock()
//Unlock方法解除rw的写入锁状态,如果m未加写入锁会导致运行时错误。
Lock() 和 Unlock():
Lock() 加写锁,Unlock() 解写锁
package main
import (
"fmt"
"sync"
)
func main() {
var L *sync.RWMutex //读写锁
L = new(sync.RWMutex)
L.Lock() //加锁
fmt.Println("hello")
L.Unlock() //解锁
}
func (rw *RWMutex) RLock()
//RLock方法将rw锁定为读取状态,禁止其他线程写入,但不禁止读取。
func (rw *RWMutex) RUnlock()
//Runlock方法解除rw的读取锁状态,如果m未加读取锁会导致运行时错误。
RLock() 和 RUnlock():
1.RLock() 加读锁,RUnlock() 解读锁。
2.RLock() 加读锁时,如果存在写锁,则无法加读锁;当只有读锁或者没有锁时,可以加读锁,读锁可以加载多个。
3.在没有读锁的情况下调用 RUnlock() 会导致 panic 错误。
4.当RUnlock多于RLock时,会报错,进入死锁