Golang -- 互斥锁

来源:互联网 发布:服务器对应默认端口 编辑:程序博客网 时间:2024/06/01 16:28

互斥锁 sync.Mutex

sync.Mutex 只有两个公开的指针方法 Lock() 和 Unlock().
Lock() 用于锁定当前互斥量.
Unlock() 用于对互斥量解锁.

  • 如果锁定了一个已锁定的互斥锁,则进行重复加锁的goroutine将会阻塞. 当互斥锁解锁后,阻塞的goroutine会唤醒.
    演示程序:
package mainimport (    "fmt"    "sync"    "time")func main() {    var mutex sync.Mutex    fmt.Println("加锁. (main)")    mutex.Lock()    fmt.Println("锁上了 (main)")    go func() {        fmt.Println("加锁  (goroutine)")        mutex.Lock()  // 对已经加锁的mutex进行重复加锁        fmt.Println("锁上了 (goroutine)")    }()    time.Sleep(time.Second)    fmt.Println("解锁了 (main)")    mutex.Unlock()    time.Sleep(time.Second)    fmt.Println("main exit")}

演示结果:
这里写图片描述

分析:
1. 首先main线程进行加锁, 加锁后启动了goroutine,main线程睡1秒,保证goroutine运行起来.
2. goroutine启动后, 进行重复加锁操作,导致 goroutine自身阻塞了.
3. main醒来后解锁,又睡1秒,为了等待goroutine运行. goroutine加锁成功,然后打印 “锁上了 (goroutine)”后就销毁了.
4. main醒来后,打印 “main exit.” 后退出.

  • 多个goroutine抢占资源,使用互斥锁进行资源的唯一性访问.
    测试程序:
package mainimport (    "fmt"    "sync"    "time")func main() {    var mutex sync.Mutex    fmt.Println("加锁. (main)")    mutex.Lock()    fmt.Println("锁上了 (main)")    for i := 1; i <= 3; i++{        go func(i int) {            fmt.Printf("加锁  (g%d)\n", i)            mutex.Lock()  // 对已经加锁的mutex进行重复加锁            fmt.Printf("锁上了 (g%d)\n", i)        }(i)    }    time.Sleep(time.Second)  // 等待所有goroutine都运行起来    fmt.Println("解锁了 (main)")    mutex.Unlock()    time.Sleep(time.Second)  // 等待goroutine重新锁定互斥锁,只有一个能抢到互斥锁    fmt.Println("main exit")}

运行结果:
这里写图片描述

  • 当对一个未加锁的互斥锁解锁时,会引发panic. 而且是无法recover() 的panic.
package mainimport (    "fmt"    "sync")func main() {    defer func() {        fmt.Println("尝试恢复panic.")        if p := recover(); p != nil {            fmt.Println("已经恢复了 panic")        }    }()    var mutex sync.Mutex    fmt.Println("加锁")    mutex.Lock()    fmt.Println("锁上了")    fmt.Println("解锁")    mutex.Unlock()    fmt.Println("解锁了")    fmt.Println("再解锁")    mutex.Unlock()}

结果:
这里写图片描述

总结

  1. 互斥锁(sync.Mutex)是为了确保对共享资源的唯一访问设计的.
  2. 重复加锁会阻塞进行重复加锁的线程.
  3. 解锁还没有加锁的互斥锁会引发无法避免的panic.