Golang -- 互斥锁 - Go语言中文社区

Golang -- 互斥锁


互斥锁 sync.Mutex

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

  • 如果锁定了一个已锁定的互斥锁,则进行重复加锁的goroutine将会阻塞. 当互斥锁解锁后,阻塞的goroutine会唤醒.
    演示程序:
package main

import (
    "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 main

import (
    "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 main

import (
    "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.
版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/qq_27068845/article/details/72854464
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2019-08-27 16:28:48
  • 阅读 ( 963 )
  • 分类:Go

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢