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/