According to Paul E. McKenney, Silas Boyd-Wickizer & Jonathan Walpole in a practical tech report about “the RCU API and how to apply it”
Most major Linux kernel subsystems use RCU as a synchronization mechanism. […] Understanding RCU is now a prerequisite for understanding the Linux implementation and its performance.
The success of RCU is, in part, due to its high performance in the presence of concurrent readers and updaters.
The RCU API facilitates this with two relatively simple
primitives: readers access data structures within RCU
read-side critical sections, while updaters use RCU synchronization to wait for all pre-existing RCU read-side
critical sections to complete. When combined, these primitives allow threads to concurrently read data structures,
even while other threads are updating them. (LINK)
Then see McKenney’s more general (and fanciful) treatment in “Structured Deferral: Synchronization via Procrastination“, which also discusses hazard pointers.