面试题答案
一键面试Mutex锁出现死锁的常见原因
- 重复锁定:对已经锁定的Mutex再次锁定而未解锁。
- 未解锁:获取锁后由于程序逻辑错误,没有执行解锁操作。
- 交叉锁定:多个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
后,未解锁就再次尝试锁定,这会导致死锁。
发现死锁的方法
- 运行时检测: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
- 使用调试工具:如
delve
调试器,可以在代码中设置断点,逐步执行代码,观察锁的状态变化,有助于发现死锁的潜在原因。