Hazard pointers and epoch reclamation
Decide when a removed concurrent node can be reclaimed without invalidating readers that still hold references.
On this page
The question for today
What you’ll understand
- Distinguish logical removal, retirement, and physical reclamation.
- Trace the publish-and-validate pattern of hazard protection.
- Compare object-specific protection with epoch-based quiescence.
Removing a node from a shared list does not remove its address from another thread’s registers. A reader can load a pointer, pause, and resume after an updater has unlinked and freed the object. A successful CAS on the list is therefore insufficient to make deallocation safe. Reclamation is a protocol about outstanding access permissions. Hazard pointers announce particular objects that may still be accessed; epoch schemes announce participation in a broader period during which old references may remain live.
Publish protection, then validate the source
A hazard-protected reader first obtains a candidate pointer from the shared source, publishes that candidate in its hazard record, and rereads the source. If the source changed, it retries before dereferencing the candidate. The validation closes the window in which the candidate could have been removed before the reader announced protection. If validation succeeds under the chosen protocol, the reader may inspect the object while keeping its protection active. Clearing the record ends that permission; retaining a raw pointer after clearing it defeats the protocol.
The order of these actions is a memory-model requirement, not merely the order in which lines appear in source code. Publication, validation, and a reclaimer’s scan require the barriers or atomic orderings prescribed by a proven implementation. Do not replace them with relaxed atomics because a stress test passed. A hazard record also protects an object lifetime, not arbitrary concurrent writes to its fields. Those fields need immutability, atomic access, or another synchronization mechanism. Preventing use-after-free and preventing data races are different achievements.
Retirement is not deallocation
After unlinking an object, an updater retires it into a deferred list. A hazard scan collects the currently protected addresses and reclaims eligible retired objects that are absent, following the protocol’s ordering and ownership rules. Batching amortizes scans, but retains memory longer. A thread paused with two valid hazard records can pin those particular objects; that does not mean it pins every object retired afterward. Bounds on total retained storage still depend on retirement thresholds, registration policy, and the particular algorithm. Preventing unsafe address reuse does not rule out every logical ABA transition; the surrounding algorithm still needs its own state-change argument.
Epoch-based reclamation typically brackets operations with an active interval and an announced epoch. A retired object remains unavailable for reuse until the scheme establishes that participants which could hold its old references have passed a quiescent state or otherwise advanced safely. Exact advancement rules differ across implementations. A stalled active participant can prevent reclamation of a growing set of later retired objects. This is why a lock-free data structure does not automatically provide a nonblocking or bounded-memory reclamation system under arbitrary thread suspension.
Choose a protocol using pause behavior and access patterns
Hazard pointers suit explicit protection of a small number of nodes and can tolerate delayed threads while limiting which objects those threads directly pin. Epoch schemes can make traversal cheaper because a single active interval covers many nodes, but a thread must not silently remain active across unbounded blocking work. Investigate the library’s rules for nested guards, thread deregistration, exceptions, and asynchronous callbacks. Copying a pointer into a callback does not extend a guard’s lifetime unless the API explicitly provides that ownership transfer.
Estimate retention from the workload rather than claiming that reclamation is free. At a steady retirement rate and an approximately fixed delay, rate times delay estimates pending bytes; bursts and stalled participants can exceed that estimate. In the queue lab, interpret arrivals as retirement events and service as reclamation events. For each independent fixed-rate experiment choose Reset, explicitly set both rates, predict, then Play or Step. Compare arrival two with service three against a fresh Reset followed by arrival two and service one. The first drains and the second grows from four initial items. A control edit retains elapsed time and recomputes from that initial backlog, rather than switching reclamation capacity within a retained history. This is only a fluid analogy. It does not implement hazard scans, epoch advancement, pointer reuse, or a proof that a node may safely be freed.
Work it through
Compute one protected retirement batch
Four threads register two hazard slots each. A correctly synchronized scan observes protected retired nodes B and E in the retirement set {A,B,C,D,E,F}. Every node occupies 64 bytes. Assume all other protocol conditions for reclamation are satisfied.
The scan considers 4×2=8 registered hazard records. Multiple records may repeat an address or be empty; eight records do not imply eight distinct protected nodes.
Intersecting the protected addresses with the six-node retirement set leaves B and E protected. A, C, D, and F are eligible, giving four nodes to reclaim in this batch.
Reclaiming four nodes returns 4×64=256 bytes. The two protected retired nodes retain 2×64=128 bytes, excluding allocator metadata and hazard-record storage.
This batch frees 256 bytes and retains 128 bytes. Those numbers rely on a valid protection/scan protocol; an unsynchronized address snapshot is not enough.
The living notebook
Explore the model
Interactive lab · queue
Retirement pressure and reclamation capacity
Interpret arrival as retired nodes per second and service as reclaimed nodes per second. For separate fixed-rate runs choose Reset, explicitly set both rates, predict, then Play or Step: compare (2,3) with Reset plus (2,1). Editing a rate retains elapsed time and recomputes from four initial nodes, without preserving a previous backlog.
- Fluid backlog
- 4
- Net rate · λ − μ
- −1 /s
- M/M/1 mean residence
- 1 s
Fluid backlog starts at 4 and follows max(0, 4 + (λ − μ)t). The separate M/M/1 residence-time formula assumes Poisson arrivals, exponential service and λ < μ. Parameter changes pause playback and recompute the model at the current elapsed time. Reset restores both parameters and returns time to zero. Playback starts paused. Adjust either parameter, then choose Play or Step.
Look forThis backlog analogy exposes retention pressure but cannot decide whether any pointer is safe to reclaim. The M/M/1 readout is not a hazard-pointer performance guarantee.
Pause & reason
Check your understanding
Your turn
Try it yourself
A service retires 1,000 nodes per second, each 64 bytes. Compare the steady-flow pending-memory estimate at delays of 0.25 seconds and two seconds. Is either a worst-case bound for epoch reclamation?
Take a moment to make a prediction or work it out on paper. Open a hint when you need one.
Give me a hint
Convert nodes per second times seconds into nodes, then multiply by bytes per node. Consider an indefinitely stalled active participant.
Compare with the solution
At 0.25 seconds the estimate is 250 nodes or 16,000 bytes. At two seconds it is 2,000 nodes or 128,000 bytes, eight times larger. Neither is a worst-case bound: bursts, delayed scans, or an active participant preventing epoch progress can retain substantially more memory. Allocation overhead is also excluded.
Keep the idea
Take it with you
- A retired object can remain accessible to an earlier reader.
- Hazard publication requires validation and a proven ordering protocol.
- Evaluate reclamation progress and retained memory separately from data-structure progress.
Read further
Original sources and deeper explanations to follow at your own pace.
Optional progress, saved in this browser when available. Revisit any lesson at any time.
Lesson not marked complete.