go
runtime_error
ai_generated
true
fatal error: sync: unlock of unlocked mutex
ID: go/mutex-lock-already-held
85%Fix Rate
85%Confidence
1Evidence
2023-01-15First Seen
Version Compatibility
| Version | Status | Introduced | Deprecated | Notes |
|---|---|---|---|---|
| Go 1.18 | active | — | — | — |
| Go 1.19 | active | — | — | — |
| Go 1.20 | active | — | — | — |
| Go 1.21 | active | — | — | — |
| Go 1.22 | active | — | — | — |
Root Cause
Calling Unlock() on a sync.Mutex that was not locked by the same goroutine, or double-unlocking a mutex.
generic中文
在同一个协程中对未锁定的 sync.Mutex 调用 Unlock(),或者对同一个互斥锁重复解锁。
Official Documentation
https://pkg.go.dev/sync#MutexWorkarounds
-
95% success Always pair Lock() and Unlock() in the same function, using defer immediately after Lock() to avoid mismatches
Always pair Lock() and Unlock() in the same function, using defer immediately after Lock() to avoid mismatches
-
85% success Use sync.Mutex.TryLock() (Go 1.18+) to check if lock is held before unlocking, but prefer structured patterns
Use sync.Mutex.TryLock() (Go 1.18+) to check if lock is held before unlocking, but prefer structured patterns
中文步骤
始终在同一个函数中配对 Lock() 和 Unlock(),在 Lock() 后立即使用 defer 以避免不匹配
使用 sync.Mutex.TryLock()(Go 1.18+)在解锁前检查锁是否被持有,但推荐使用结构化模式
Dead Ends
Common approaches that don't work:
-
75% fail
Defer runs even if the lock was never acquired (e.g., due to early return), causing an unlock of an unlocked mutex.
-
90% fail
The Go runtime checks that the unlocking goroutine is the same one that locked it; cross-goroutine unlocks panic.