How to implement lock-free skip list
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.
Introduction
A lock-free skip list is a concurrent ordered set or map built from layered linked lists and atomic compare-and-swap operations instead of coarse locks. The core challenge is not basic skip-list search. It is making insert and delete correct while other threads are traversing or modifying the same structure. A practical implementation usually follows the well-known pattern of logical deletion first, then physical unlinking.
Start With the Right Node Structure
A concurrent skip-list node needs:
- a key
- a top level
- one next pointer per level
- a way to mark links during deletion
In Java, AtomicMarkableReference is a common building block:
The mark bit is critical. It lets one thread declare a link logically deleted before another thread physically unlinks it.
Use Head and Tail Sentinels
Most implementations add sentinel nodes for negative and positive infinity. That makes traversal logic simpler because every search starts from a well-defined top-left corner.
With this setup, every search can walk from head toward tail without null checks driving the whole algorithm.
The Search Routine Must Also Help With Cleanup
The heart of a lock-free skip list is a find method that returns predecessors and successors for every level. While traversing, it also notices marked nodes and helps unlink them.
This "helping" behavior is what keeps the structure moving forward without central locking.
Insert Bottom-Up With CAS
Insertion typically works like this:
- choose a random top level
- call
find - if the key already exists, stop
- link level
0first using CAS - link higher levels one by one
The bottom-level link linearizes the insertion. Higher levels can be retried until they succeed.
Delete by Marking, Then Unlinking
Deletion is usually split into two phases:
- logical deletion by marking next pointers
- physical removal by unlinking the node from predecessors
That split is what makes concurrent traversals safe. Once the bottom-level link is marked, the key is considered deleted even if higher-level cleanup is still happening.
This is much safer than trying to remove the node from all levels atomically in one impossible step.
Random Levels Still Matter
Even in the lock-free version, the skip list depends on random tower heights for expected logarithmic performance. The concurrency logic changes the pointer management, but not the probabilistic balancing idea.
The random-level generator does not need cryptographic quality. It just needs a reasonable geometric distribution.
Common Pitfalls
The biggest mistake is trying to write a "lock-free" skip list without a clear logical-deletion protocol. Another is forgetting that traversal must help clean up marked nodes or the structure accumulates garbage links and progress degrades. Memory reclamation is another hard problem in lower-level languages, because removed nodes may still be visible to racing readers. In Java, the garbage collector helps, but correctness is still subtle. Finally, a lock-free skip list is not a beginner data-structure project; if production correctness matters more than learning value, a battle-tested concurrent collection is often the better choice.
Summary
- A lock-free skip list uses atomic link updates instead of coarse locks.
- Nodes typically store per-level atomic next pointers with mark bits.
- '
findmust both search and help unlink logically deleted nodes.' - Insertions usually linearize at the bottom-level CAS.
- Deletions are typically logical first, physical second.
- If you need production reliability, prefer a mature concurrent implementation unless you truly need a custom one.
Related reading
- How to implement Ologn decrease-key operation for min-heap based Priority Queue?
- How to implement Prim's algorithm with a Fibonacci heap?
- How to implement range search in KD-Tree
- How to implement RSI Divergence in Python
- How to implement request-reply (synchronous) messaging paradigm in Kafka?
- How to implement segment trees with lazy propagation?
- How to implement multithread safe singleton in C11 without using mutex
- How to increase debezium / kafka connect performance for initial snapshot of millions of records and enable snapshot parallely if possible?

DSA Fundamentals
Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.