1、概述
Mutex 是一个互斥锁,可以创建为其他结构体的字段;零值为解锁状态。Mutex 类型的锁和线程无关,可以由不同的线程加锁和解锁。
type Mutex struct { state int32 sema uint32 }
2、方法
Lock
func (m *Mutex) Lock()
Lock方法锁住m,如果m已经加锁,则阻塞直到m解锁。
Unlock
func (m *Mutex) Unlock()
Unlock方法解锁m,如果m未加锁会导致运行时错误。锁和协程无关,可以由不同的协程加锁和解锁。
注意:
- 在一个 goroutine 获得 Mutex 后,其他 goroutine 只能等到这个 goroutine 释放该 Mutex
- 使用 Lock() 加锁后,不能再继续对其加锁,直到利用 Unlock() 解锁后才能再加锁
- 在 Lock() 之前使用 Unlock() 会导致 panic 异常
- 已经锁定的 Mutex 并不与特定的 goroutine 相关联,这样可以利用一个 goroutine 对其加锁,再利用其他 goroutine 对其解锁
- 在同一个 goroutine 中的 Mutex 解锁之前再次进行加锁,会导致死锁
- 适用于读写不确定,并且只有一个读或者写的场景
3、示例
示例一:
var mutex sync.Mutex //互斥锁 func printer(str string){ mutex.Lock() //加锁 defer mutex.Unlock() //解锁 for _,ch:=range str{ fmt.Printf("%c",ch) time.Sleep(time.Millisecond*300) } } func user1(){ printer("hello ") } func user2(){ printer("world") } func main() { go user1() go user2() for { ; } }
输出:
hello world
示例二:
package main import ( "fmt" "sync" "time" ) func main() { var mutex sync.Mutex wait := sync.WaitGroup{} fmt.Println("Locked") mutex.Lock() for i := 1; i <= 3; i++ { wait.Add(1) go func(i int) { fmt.Println("Not lock:", i) mutex.Lock() fmt.Println("Lock:", i) time.Sleep(time.Second) fmt.Println("Unlock:", i) mutex.Unlock() defer wait.Done() }(i) } time.Sleep(time.Second) fmt.Println("Unlocked") mutex.Unlock() wait.Wait() }
输出:
Locked Not lock: 3 Not lock: 2 Not lock: 1 Unlocked Lock: 3 Unlock: 3 Lock: 2 Unlock: 2 Lock: 1 Unlock: 1
4、总结
互斥锁相互排斥,谁抢到锁谁执行。
参考:https://shockerli.net/post/golang-pkg-mutex/
参考:https://blog.csdn.net/weixin_43851310/article/details/87890645