Sign Up Sign Up


Have an account? Sign In Now

Sign In Sign In


Forgot Password?

Don't have account, Sign Up Here

Forgot Password Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.


Have an account? Sign In Now

You must login to ask a question.


Forgot Password?

Need An Account, Sign Up Here

You must login to add post.


Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

RTSALL Logo RTSALL Logo
Sign InSign Up

RTSALL

RTSALL Navigation

  • Home
  • Tools
    • Run Code
    • JSON Beautifier
    • Regex Tester
    • Diff Checker
    • JWT Decoder
    • UUID Generator
    • .htaccess Generator
    • YAML/JSON Converter
    • SQL Formatter
    • Cron Generator
    • JSON to CSV/Excel
    • System Design Estimator
  • DSA
    • All DSA Problems
    • Online C++ Runner
    • Arrays, Strings & Cache
    • Two Pointers & Sliding Window
    • Linked Lists & Custom Allocators
    • Stacks, Queues & Ring Buffers
    • Trees, BSTs & Indexes
    • Tries & Prefix Search
    • Heaps & Priority Schedulers
    • Hashing & Collision Resolution
    • Graphs & Network Topologies
    • Dynamic Programming
    • Advanced Bitmask & Tree DP
    • Greedy & Resource Allocation
    • Binary Search & State Spaces
    • Bit Manipulation & Low-Level
    • System-Scale & Probabilistic
  • AI Utilities
    • Token Counter
    • JSON Schema Compiler
    • Fine-Tuning JSONL Converter
    • Vector RAG Playground
    • Prompt Optimizer & Architect
    • LLM GPU VRAM Calculator
  • Finance Tools
    • Compound Interest Calculator
    • Simple Interest Calculator
    • Present Value (PV) Calculator
    • Future Value (FV) Calculator
    • NPV Calculator
    • IRR Calculator
    • CAGR Calculator
    • Dividend Income Calculator
    • Yield on Cost Calculator
    • Dividend Payout Ratio
    • WACC Calculator
    • CAPM & Cost of Equity
    • Cost of Debt Calculator
    • DCF Valuation Calculator
    • Enterprise Value Calculator
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Tools
    • Run Code
    • JSON Beautifier
    • Regex Tester
    • Diff Checker
    • JWT Decoder
    • UUID Generator
    • .htaccess Generator
    • YAML/JSON Converter
    • SQL Formatter
    • Cron Generator
    • JSON to CSV/Excel
    • System Design Estimator
  • DSA
    • All DSA Problems
    • Online C++ Runner
    • Arrays, Strings & Cache
    • Two Pointers & Sliding Window
    • Linked Lists & Custom Allocators
    • Stacks, Queues & Ring Buffers
    • Trees, BSTs & Indexes
    • Tries & Prefix Search
    • Heaps & Priority Schedulers
    • Hashing & Collision Resolution
    • Graphs & Network Topologies
    • Dynamic Programming
    • Advanced Bitmask & Tree DP
    • Greedy & Resource Allocation
    • Binary Search & State Spaces
    • Bit Manipulation & Low-Level
    • System-Scale & Probabilistic
  • AI Utilities
    • Token Counter
    • JSON Schema Compiler
    • Fine-Tuning JSONL Converter
    • Vector RAG Playground
    • Prompt Optimizer & Architect
    • LLM GPU VRAM Calculator
  • Finance Tools
    • Compound Interest Calculator
    • Simple Interest Calculator
    • Present Value (PV) Calculator
    • Future Value (FV) Calculator
    • NPV Calculator
    • IRR Calculator
    • CAGR Calculator
    • Dividend Income Calculator
    • Yield on Cost Calculator
    • Dividend Payout Ratio
    • WACC Calculator
    • CAPM & Cost of Equity
    • Cost of Debt Calculator
    • DCF Valuation Calculator
    • Enterprise Value Calculator
  • About Us
  • Blog
  • Contact Us
Home/Questions/Q 3518
Next
In Process

RTSALL Latest Articles

Ahmedelkomy
Ahmedelkomy
Asked: September 11, 20262026-09-11T09:51:15-05:00 2026-09-11T09:51:15-05:00In: Data Structures & Algorithms, Linked Lists & Custom Allocators

How to design a thread-safe LRU Cache in O(1) without memory leaks?

We are building an in-memory session cache for an API gateway handling 50k requests/sec. We need an LRU (Least Recently Used) cache where both get() and put() operations happen strictly in O(1) time.

A lot of implementations I see online either use standard library ordered dicts or clumsy doubly linked lists that trigger dangling pointers and memory leaks when nodes get evicted. What is the standard architectural pattern used by experienced engineers to build a bulletproof LRU cache?

  • 0
  • 2 2 Answers
  • 0 Followers
  • 0
  • Share
    Share
    • Share on Facebook
    • Share on Twitter
    • Share on LinkedIn
    • Share on WhatsApp

Leave an answer
Cancel reply

You must login to add an answer.


Forgot Password?

Need An Account, Sign Up Here

2 Answers

  • Voted
  • Oldest
  • Recent
  • Random
  1. Abhishek
    Abhishek Begginer
    2026-09-11T21:26:34-05:00Added an answer on September 11, 2026 at 9:26 pm

    In C++, a common mistake when building an LRU cache is using std::list which allocates each node on the heap separately. In production, we use a custom intrusive doubly linked list with a pool or flat hash map (std::unordered_map) to guarantee O(1) latency with minimal heap fragmentation.

    Modern C++20 Solution (Fully Runnable)

    #include <iostream>
    #include <unordered_map>
    #include <memory>
    
    class LRUCache {
        struct Node {
            int key;
            int value;
            Node* prev;
            Node* next;
            Node(int k = 0, int v = 0) : key(k), value(v), prev(nullptr), next(nullptr) {}
        };
    
        int capacity;
        std::unordered_map<int, std::unique_ptr<Node>> node_storage;
        std::unordered_map<int, Node*> map;
        Node* head;
        Node* tail;
    
        void remove(Node* node) {
            node->prev->next = node->next;
            node->next->prev = node->prev;
        }
    
        void insertAtFront(Node* node) {
            node->next = head->next;
            node->prev = head;
            head->next->prev = node;
            head->next = node;
        }
    
    public:
        LRUCache(int cap) : capacity(cap) {
            head = new Node();
            tail = new Node();
            head->next = tail;
            tail->prev = head;
        }
    
        ~LRUCache() {
            delete head;
            delete tail;
        }
    
        int get(int key) {
            auto it = map.find(key);
            if (it == map.end()) return -1;
            Node* node = it->second;
            remove(node);
            insertAtFront(node);
            return node->value;
        }
    
        void put(int key, int value) {
            auto it = map.find(key);
            if (it != map.end()) {
                Node* node = it->second;
                node->value = value;
                remove(node);
                insertAtFront(node);
            } else {
                if ((int)map.size() >= capacity) {
                    Node* lru = tail->prev;
                    remove(lru);
                    int lru_key = lru->key;
                    map.erase(lru_key);
                    node_storage.erase(lru_key);
                }
                auto new_node = std::make_unique<Node>(key, value);
                Node* raw_ptr = new_node.get();
                insertAtFront(raw_ptr);
                map[key] = raw_ptr;
                node_storage[key] = std::move(new_node);
            }
        }
    };
    
    int main() {
        LRUCache cache(2);
        cache.put(1, 10);
        cache.put(2, 20);
        std::cout << "get(1): " << cache.get(1) << "n"; // returns 10
        cache.put(3, 30);                                  // evicts key 2
        std::cout << "get(2): " << cache.get(2) << "n"; // returns -1 (evicted)
        return 0;
    }
    

    Memory Safety: std::unique_ptr owns the node memory, preventing any memory leaks even if exceptions occur.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
  2. Anonymous
    Anonymous Begginer
    2026-09-11T09:51:17-05:00Added an answer on September 11, 2026 at 9:51 am

    Building an LRU cache from scratch is one of the best ways to understand how data structures combine in real systems. The industry standard pattern is combining two complementary structures:

    1. A Hash Map: Gives you O(1) key-to-node lookups.
    2. A Doubly Linked List (DLL) with Dummy Head & Tail: Gives you O(1) node insertion at the front (most recent) and O(1) node removal from the back (least recent).

    The secret trick that eliminates 90% of bug-prone null checks is using sentinel (dummy) head and tail nodes. Instead of constantly checking if (head == null) or if (node->prev == null), the dummy head and tail are always linked together: head <-> tail. Any real data node always lives safely in between them!


    Architectural Diagram

    [Head Dummy] <---> [Most Recent Node] <---> [Older Node] <---> [Tail Dummy]
                                                                          ^
                                                          Evict from here |
    

    Clean, Idiomatic Python 3.12 Implementation

    class Node:
        __slots__ = ('key', 'val', 'prev', 'next')
        def __init__(self, key: int = 0, val: int = 0):
            self.key = key
            self.val = val
            self.prev = None
            self.next = None
    
    class LRUCache:
        def __init__(self, capacity: int):
            self.cap = capacity
            self.cache: dict[int, Node] = {}
            
            # Dummy sentinel boundaries
            self.head = Node()
            self.tail = Node()
            self.head.next = self.tail
            self.tail.prev = self.head
    
        def _remove(self, node: Node) -> None:
            """Unlinks a node from its current position."""
            node.prev.next = node.next
            node.next.prev = node.prev
    
        def _insert_at_front(self, node: Node) -> None:
            """Inserts node right after head (most recently used)."""
            node.next = self.head.next
            node.prev = self.head
            self.head.next.prev = node
            self.head.next = node
    
        def get(self, key: int) -> int:
            if key not in self.cache:
                return -1
            node = self.cache[key]
            # Refresh access: move to front
            self._remove(node)
            self._insert_at_front(node)
            return node.val
    
        def put(self, key: int, value: int) -> None:
            if key in self.cache:
                node = self.cache[key]
                node.val = value
                self._remove(node)
                self._insert_at_front(node)
            else:
                if len(self.cache) >= self.cap:
                    # Evict least recently used (node right before tail)
                    lru = self.tail.prev
                    self._remove(lru)
                    del self.cache[lru.key]
                    
                new_node = Node(key, value)
                self.cache[key] = new_node
                self._insert_at_front(new_node)
    

    Why Storing the Key Inside the Node is Crucial

    Notice that the Node class stores both key and val. Many developers forget to store key in the node and only store val. But when the cache reaches full capacity and you evict tail.prev, how do you delete that entry from the hash map? Without node.key, you’d have to search the entire hash map in O(N) time, destroying your O(1) guarantee!


    Thread Safety in Production

    If multiple threads access this cache concurrently:

    • In Python, use threading.Lock() around get and put.
    • In Go or C++, a Read-Write Lock (sync.RWMutex / std::shared_mutex) is often tempting, but remember: even a get() operation mutates the linked list (to move the accessed item to the front)! Therefore, standard read locks are not enough—you must acquire an exclusive lock or use lock striping across multiple shards.
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp

Sidebar

Ask A Question
  • Popular
  • Answers
  • Queryiest

    What is a database?

    • 3 Answers
  • Anonymous

    How to rotate an array in-place with O(1) space and ...

    • 3 Answers
  • hannah

    What steps can businesses take to identify the most valuable ...

    • 2 Answers
  • Vikram
    aarav0 added an answer Direct Technical Solution: Unlike IVFFlat (which partitions vector spaces with… September 11, 2026 at 9:57 pm
  • Abhishek
    Abhishek added an answer Direct Technical Solution: In C++20, range view adaptors (like std::views::filter,… September 11, 2026 at 9:57 pm
  • Sneha Patel
    Anonymous added an answer Direct Technical Solution: torch.cuda.empty_cache() releases only cached (unallocated) blocks back… September 11, 2026 at 9:57 pm

Related Questions

  • pgvector: HNSW index build fails with out-of-memory or high swap: ...

    • 1 Answer
  • Why does std::views::filter on temporary containers trigger undefined behavior and ...

    • 1 Answer
  • PyTorch RuntimeError: CUDA out of memory: Why torch.cuda.empty_cache() fails & ...

    • 1 Answer
  • Next.js 15: Error: Route used "params" without awaiting it (Asynchronous ...

    • 1 Answer
  • Task Scheduler with Cooldowns: Closed-form mathematical formula vs Priority Queue ...

    • 2 Answers

Top Members

Queryiest

Queryiest

  • 201 Questions
  • 295 Points
Enlightened
Anonymous

Anonymous

  • 11 Questions
  • 42 Points
Begginer
paperubofficial

paperubofficial

  • 0 Questions
  • 22 Points
Begginer

Trending Tags

ai asp.net aws basics aws certification aws console aws free tier aws login aws scenario-based questions c++ career cyber security cyber security interview git java javascript jobs jquery net core net core interview questions sql

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • DSA Problems
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • New Questions
  • Trending Questions
  • Must read Questions
  • Hot Questions

Footer

About Us

  • Meet The Team
  • Blog
  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy
  • Disclaimer
  • Terms & Conditions

Help

  • Knowledge Base
  • Support

Follow

© 2023-25 RTSALL. All Rights Reserved

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.