Map

Epoch-based reclamation

Wiki conceptconcurrencymemory-safety โ†ณ show in map Markdown
title
Epoch-based reclamation
type
concept
summary
Lock-free memory reclamation scheme where freed nodes wait in per-thread limbo until all threads have advanced past the retirement epoch
tags
concurrency, memory-safety
created
2026-05-19
updated
2026-05-19

Epoch-based reclamation (EBR) is a memory-management technique for lock-free data structures. The problem it solves: when a thread removes a node from a concurrent structure, other readers might still hold a pointer to that node. Freeing immediately would let those readers dereference freed memory. Reference counting works but adds per-access atomic increments. EBR avoids the per-access overhead.

The scheme works in three pieces:

  • A global epoch counter, incremented by reclaimers. Two or three values rotate (e.g., 0, 1, 2).
  • Each registered thread maintains a local epoch stamped when it pins, and a limbo list of nodes it has retired in that epoch.
  • Before touching the structure, a thread pins by copying the global epoch into its local. Pinned means "I might be holding pointers from this epoch onward."

When a node is removed it's not freed โ€” it's appended to the current thread's limbo list, tagged with the current global epoch. A node is safe to free only once every registered thread's local epoch has advanced past the node's retirement epoch. A background or piggybacked pass walks the limbo lists, frees what's safe, and the global counter advances.

The cost model is the opposite of refcounting: zero per-access overhead in the hot path (one relaxed read of the global epoch on pin/unpin), at the cost of bounded memory bloat โ€” freed memory can sit in limbo as long as one thread stays pinned. The standard mitigation is a per-thread retirement threshold that forces a reclamation pass when the limbo list grows.

EBR is the default reclamation scheme in many lock-free libraries: Crossbeam in Rust, userspace RCU (URCU) on Linux, the gregburd/skiplist C library, and most academic lock-free skip-list and queue implementations. The main alternative is hazard pointers, which trades higher per-access overhead for tighter worst-case memory bounds.