Skip to content

go.empty_critical_section

Performance Medium

Detects mutex locks protecting empty or trivial critical sections, causing unnecessary contention.

Empty critical sections cause:

  • Unnecessary contention - Goroutines block for nothing
  • Deadlock risk - Complex lock patterns with no benefit
  • Performance degradation - Lock overhead without protection
  • Code smell - Often indicates incomplete implementations
// ❌ Before (pointless locking)
var mu sync.Mutex
func process() {
mu.Lock()
defer mu.Unlock()
// Nothing protected!
}
// Also problematic
func update() {
mu.Lock()
mu.Unlock() // Immediate unlock
doWork() // Work happens outside lock
}
// ✅ After (meaningful critical section)
var mu sync.Mutex
var counter int
func process() {
mu.Lock()
defer mu.Unlock()
counter++ // Actually protected
}
  • Lock()/Unlock() with nothing between them
  • defer mu.Unlock() with no protected operations
  • Critical sections with only logging
  • Lock/unlock without shared state access

Unfault flags these for manual review since the fix depends on intent:

// Option 1: Remove unnecessary lock
func process() {
doWork() // If no shared state
}
// Option 2: Add protected operations
func process() {
mu.Lock()
sharedData = newValue
mu.Unlock()
doWork()
}