Avoid Empty Critical Sections

ID

go.avoid_empty_critical_sections

Severity

low

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

Go

Tags

reliability, suspicious

Description

Reports a mutex Lock() immediately followed by an Unlock() on the same receiver with nothing in between — either as two adjacent statements (mu.Lock(); mu.Unlock()) or as a lock followed immediately by a deferred unlock (mu.Lock(); defer mu.Unlock()).

Rationale

An empty critical section acquires and releases the lock without touching any shared state, so it protects nothing and is pure synchronization overhead. It is almost always leftover from deleted code, or a guard that was placed on the wrong statement. Only a Lock/Unlock pair on the same receiver is flagged; a lock and an unlock on different receivers, or any statement between them, is left alone.

c.mu.Lock() // FLAW — released immediately, nothing protected
c.mu.Unlock()

c.mu.Lock() // OK — guards a real update
c.n++
c.mu.Unlock()

Remediation

Move the work that must be protected inside the critical section, or delete the empty lock/unlock pair entirely.