Choosing a lock

July 12, 2026 ยท View on GitHub

Start with sync.Mutex or sync.RWMutex. Choose Powerlock when the lock itself needs cancellation, bounded waiting, diagnostics, metrics, or keyed exclusion.

TypeUse it whenWaiting and failure behaviorObservationZero value
ContextRWMutexA queued acquisition must obey a contextFIFO; context methods return typed cancellation or deadline errorsSnapshotReady, empty name
FairRWMutexThe FIFO guarantee should be explicit in the type nameAlias of ContextRWMutexSnapshotReady, empty name
CancelRWMutexShutdown must permanently reject queued and future workFIFO; cancellation is irreversible; blocking methods panic after cancellationSnapshotReady, empty name
MaxRWMutexThe number of blocked acquisitions must be boundedFIFO; excess blocking calls return ErrMaxWaiting, while Lock and RLock panicSnapshotReady, one waiter maximum
ObservedRWMutexEvery wait, acquisition, release, rejection, and failed try needs structured dataFIFO; context-awareStructured events, exact guards, snapshots, optional pprof and Prometheus adaptersReady with observation disabled
WatchdogRWMutexSlow waits and long holds need caller stacks and threshold reportsFIFO; diagnostics never force releaseObserved events plus wait and exact-hold threshold eventsReady with an empty name; thresholds and observation disabled
KeyedMutex[K]Work sharing a key must serialize while different keys proceed independentlyFIFO per key; context-aware; new keys can be bounded with ErrMaxKeysPer-key snapshot and exact key guardReady, 1024 active keys maximum

ContextMutex, FairMutex, CancelMutex, MaxMutex, ObservedMutex, and WatchdogMutex are exclusive-only forms for code that does not need reader sharing.

Lock-order diagnostics

Powerlock does not infer which locks one goroutine owns. Go exposes no supported current-goroutine identity, so automatic ownership tracking would depend on runtime details that can change and would make reports unreliable.

A future opt-in diagnostic package can instead require an explicit logical-operation scope. Guarded acquisitions would add scope-local ordering edges with acquisition stacks and reject an edge that closes a cycle with a typed conflict report. The design remains deferred because every participating acquisition must carry the scope; partial adoption could otherwise imply safety it cannot provide.

Read/write conversion

Powerlock does not currently upgrade read ownership or downgrade write ownership. A blocking upgrade can deadlock when multiple readers retain their locks while waiting to become the writer, and releasing a read lock before an ordinary write acquisition is not atomic.

If conversion is added after v0.1, it will be guard-only. TryUpgrade would retain the read guard on failure and succeed only when that guard is the sole reader and no waiter is queued. Downgrade would atomically replace an exact write guard with a read guard. Either successful conversion would use a fresh acquisition identifier so diagnostics continue to pair one mode and hold interval exactly.

See BENCHMARKS.md for measured overhead, LIMITATIONS.md for tradeoffs, and SPEC.md for exact behavior.