MST

星途 面试题库

面试题:Go语言中Mutex锁死锁的常见原因及一个简单死锁场景分析

在Go语言中,Mutex锁出现死锁通常有哪些原因?请举例描述一个简单的会导致Mutex锁死锁的代码场景,并说明如何发现这种死锁。
44.9万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

Mutex锁出现死锁的常见原因

  1. 重复锁定:对已经锁定的Mutex再次锁定而未解锁。
  2. 未解锁:获取锁后由于程序逻辑错误,没有执行解锁操作。
  3. 交叉锁定:多个goroutine之间以不同顺序获取多个Mutex锁,形成循环依赖。

导致Mutex锁死锁的代码场景示例

package main

import (
    "fmt"
    "sync"
)

var mu sync.Mutex

func main() {
    mu.Lock()
    fmt.Println("已锁定")
    mu.Lock() // 重复锁定,导致死锁
    fmt.Println("第二次锁定")
    mu.Unlock()
    mu.Unlock()
}

在上述代码中,main函数中第一次锁定mu后,未解锁就再次尝试锁定,这会导致死锁。

发现死锁的方法

  1. 运行时检测:Go语言的运行时系统内置了死锁检测机制。当程序发生死锁时,运行时会打印出详细的死锁信息,包括死锁发生的goroutine堆栈跟踪,帮助定位问题代码。例如上述死锁代码运行时,Go运行时会输出类似如下信息:
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [semacquire]:
sync.runtime_Semacquire(0x140000c4018)
        /usr/local/go/src/runtime/sema.go:71 +0x32
sync.(*Mutex).lock(0x140000c4010)
        /usr/local/go/src/sync/mutex.go:81 +0x8c
sync.(*Mutex).Lock(...)
        /usr/local/go/src/sync/mutex.go:49
main.main()
        /Users/user/go/src/yourpackage/main.go:10 +0x58
  1. 使用调试工具:如delve调试器,可以在代码中设置断点,逐步执行代码,观察锁的状态变化,有助于发现死锁的潜在原因。