Skip to content

Lock or Hold Until Use

Concurrency protocol — instantiates Use-Time Precondition Binding

Takes an exclusive hold on the resource at check time and keeps it through the use, so the checked condition cannot change inside the gap.

Lock or Hold Until Use closes the check–use gap by exclusion: at the moment you verify the precondition, you also take an exclusive hold on the resource, and you keep that hold until the use completes. Because no one else can touch the state while you hold it, the condition you checked cannot change underneath you — check and use become, in effect, one indivisible span. Its defining move is pessimistic: it prevents the race rather than detecting it after the fact. That is the opposite bet from the version- and freshness-token mechanisms, which let everyone proceed and catch conflicts at the end; a hold pays coordination cost up front to guarantee the gap stays empty.

Example

An engineer opens a load-bearing bracket drawing in the product-lifecycle (PLM) system and checks it out. The file is now flagged "in use by A. Rivera," and everyone else sees it read-only. Rivera confirms the current revision, makes the change, and checks it back in — only then does the hold release and the next person get to edit. Without that hold, two engineers could both open revision C, both edit against it, and the second save would silently clobber the first: the exact broken binding — a check ("revision C is current") that quietly stopped being true before the use ("save") — that the lock exists to prevent. The same shape appears in a warehouse: the instant a picker is assigned a specific unit, that bin location is held to them, so a second order cannot be promised the same physical item.

How it works

  • Acquire before you rely. Taking the hold is part of the check, not a step after it; you never act on a precondition you have not first locked.
  • Hold spans the whole gap. The lock persists from verification through completion, so the window in which state could drift is physically closed, not merely watched.
  • Exclusive by construction. While the hold is live, conflicting operations are blocked or queued — refused, not just warned.
  • Release deliberately. The hold ends only when the use is done (or a timeout fires); release is what lets contention behind it resolve.

Tuning parameters

  • Lock granularity — one coarse lock versus many fine ones; coarse locks are simple but throttle throughput, fine locks scale but multiply overhead and deadlock risk.
  • Blocking versus failing — whether a would-be user waits for the hold or is turned away at once; waiting preserves fairness, failing preserves responsiveness.
  • Hold timeout — how long a hold may live before it is force-released; short timeouts stop a crashed holder from freezing everyone, but can yank a legitimately slow operation.
  • Shared versus exclusive — read-holds that coexist versus write-holds that do not; separating them lets many readers proceed while still serializing writers.
  • Acquisition order — the discipline of always taking multiple locks in one fixed order — the single most effective guard against deadlock.

When it helps, and when it misleads

Its strength is that when a wrong action on stale state is expensive or irreversible, exclusion gives the strongest guarantee on offer: the checked condition simply cannot move before you act. It is the natural fit for short, contended critical sections where correctness beats concurrency.

Its failure mode is that exclusion serializes — it trades throughput for safety, and held locks are where systems queue up and wait. Its signature pathology is deadlock: two holders each waiting on what the other holds, both stuck forever[^deadlock], alongside lock convoys and priority inversion under load. A hold that outlives its holder — a crashed process, an engineer who checked a file out and went on vacation — freezes everyone behind it, which is why force-release exists and why it is dangerous. The classic misuse is holding a lock across a slow or external call "just to be safe," turning a brief critical section into a system-wide bottleneck. The discipline is to hold the narrowest resource for the shortest span, take locks in a consistent order, and always set a timeout.

How it implements the components

  • atomic_or_exclusive_use_boundary — the exclusive hold fuses check and use into a single indivisible span; this exclusivity is the mechanism's essence.
  • reservation_or_hold_record — the lock is a concrete, observable record ("held by A. Rivera") that other actors must see and honor.
  • check_use_gap_window — the hold exists precisely to keep this window empty; it spans and neutralizes the gap rather than tolerating it.

It does not stamp a validity_window_or_lease and step away (that's Lease-Bound Capability Token) or run a conflict_abort_and_retry_policy after letting others proceed (that's Two-Phase Commit with Freshness Check); a hold buys safety with exclusivity, not with detection.

Notes

A lock guarantees the resource does not change — not that your reason for acting is still valid. If the precondition depends on state outside the lock's scope, exclusion gives false comfort. And pessimistic holding is the wrong default when contention is rare: you pay the coordination cost on every operation to prevent a collision that seldom happens, exactly the case where the optimistic, version-token mechanisms win.