<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[LLDCoding - Master LLD and Concurrency]]></title><description><![CDATA[<p>Master the two most challenging pillars of coding interviews: Low-Level Design (LLD) and Concurrency. Get in-depth articles, real-world examples, and interview patterns to ace your design round.</p>
]]></description><link>https://lldcoding.com</link><generator>RSS for Node</generator><lastBuildDate>Sun, 12 Apr 2026 00:47:24 GMT</lastBuildDate><atom:link href="https://lldcoding.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><atom:link rel="first" href="https://lldcoding.com/rss.xml"/><atom:link rel="next" href="https://lldcoding.com/rss.xml?after=Njg2OTk4MzMwM2FmMDIxYzM0ZWM3MTA0XzIwMjUtMDctMDVUMjE6MjU6MDcuMDY4Wg=="/><item><title><![CDATA[Design (LLD) Tic Tac Toe - C++]]></title><description><![CDATA[<h1>📌 1. Problem Statement</h1>
<p>Design a Tic Tac Toe game that:</p>
<ul>
<li><p>Supports configurable board size (N  N)</p>
</li>
<li><p>Supports 2 players</p>
</li>
<li><p>Validates moves</p>
</li>
<li><p>Detects win efficiently</p>
</li>
<li><p>Detects draw</p>
</li>
<li><p>Logs moves</p>
</li>
<li><p>Is extensible (AI, multiplayer, new win strategies)</p>
</li>
<li><p>Uses proper design patterns</p>
</li>
<li><p>Is written in C++ (single-threaded)</p>
</li>
</ul>
<h1>📌 2. Functional Requirements</h1>
<h3>Core Features</h3>
<ul>
<li><p>Create game with size N</p>
</li>
<li><p>Add 2 players</p>
</li>
<li><p>Players make alternate moves</p>
</li>
<li><p>Validate moves</p>
</li>
<li><p>Detect winner</p>
</li>
<li><p>Detect draw</p>
</li>
<li><p>Display result</p>
</li>
<li><p>Log game events</p>
</li>
<li><p>Allow restart (extensible)</p>
</li>
</ul>
<h1>📌 3. Non-Functional Requirements</h1>
<ul>
<li><p>Clean architecture</p>
</li>
<li><p>O(1) win detection</p>
</li>
<li><p>Extensible strategy</p>
</li>
<li><p>Easy to add AI</p>
</li>
<li><p>Maintainable code</p>
</li>
<li><p>Testable components</p>
</li>
</ul>
<h1>📌 4. High-Level Architecture</h1>
<pre><code class="language-plaintext">Game
  Board
       Cell
  Player
  WinningStrategy
  Logger
  GameState
</code></pre>
<h1>📌 5. Design Patterns Used (With Clear Reasoning)</h1>
<table>
<thead>
<tr>
<th>Pattern</th>
<th>Where Used</th>
<th>Why Used</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Strategy</strong></td>
<td>Winning algorithm</td>
<td>Switch win logic easily</td>
</tr>
<tr>
<td><strong>Factory Method</strong></td>
<td>Player creation</td>
<td>Encapsulate object creation</td>
</tr>
<tr>
<td><strong>Singleton</strong></td>
<td>Logger</td>
<td>One global logger</td>
</tr>
<tr>
<td><strong>Observer</strong></td>
<td>Logging system</td>
<td>Notify events</td>
</tr>
<tr>
<td><strong>Decorator</strong></td>
<td>AI Player</td>
<td>Add behavior dynamically</td>
</tr>
<tr>
<td><strong>Builder</strong></td>
<td>Game construction</td>
<td>Clean configuration</td>
</tr>
<tr>
<td><strong>Command</strong></td>
<td>Move execution</td>
<td>Encapsulate actions</td>
</tr>
<tr>
<td><strong>State</strong></td>
<td>Game lifecycle</td>
<td>Manage transitions</td>
</tr>
<tr>
<td><strong>Template Method</strong></td>
<td>Winning base class</td>
<td>Standard win-check structure</td>
</tr>
</tbody></table>
<h1>📌 6. Algorithms Used</h1>
<h2>🟢 1. O(1) Winning Algorithm (Optimized)</h2>
<p>Instead of scanning entire board after every move (O(n)):</p>
<p>We maintain:</p>
<pre><code class="language-plaintext">rowCount[n]
colCount[n]
diag
antiDiag
</code></pre>
<p>For Player X  +1 For Player O  -1</p>
<p>If:</p>
<pre><code class="language-plaintext">abs(rowCount[i]) == n
OR abs(colCount[i]) == n
OR abs(diag) == n
OR abs(antiDiag) == n
</code></pre>
<p> Winner found</p>
<h3>Complexity:</h3>
<ul>
<li><p>Move: O(1)</p>
</li>
<li><p>Win check: O(1)</p>
</li>
</ul>
<h2>🟢 2. Move Validation</h2>
<ul>
<li><p>Check bounds</p>
</li>
<li><p>Check if cell empty</p>
</li>
</ul>
<p>Complexity: O(1)</p>
<h2>🟢 3. Draw Detection</h2>
<pre><code class="language-plaintext">if totalMoves == n*n
</code></pre>
<h1>📌 7. Complete C++ Implementation</h1>
<h1>🔹 ENUMS</h1>
<pre><code class="language-macs">enum class Symbol { X = 1, O = -1 };
enum class GameStatus { IN_PROGRESS, DRAW, WIN };
</code></pre>
<h1>🔹 Observer Pattern</h1>
<pre><code class="language-macs">class Observer {
public:
    virtual void update(string message) = 0;
    virtual ~Observer() {}
};
</code></pre>
<h1>🔹 Singleton Logger</h1>
<pre><code class="language-macs">class Logger : public Observer {
private:
    Logger() {}
public:
    static Logger&amp; getInstance() {
        static Logger instance;
        return instance;
    }

    void update(string message) override {
        cout &lt;&lt; "[LOG] " &lt;&lt; message &lt;&lt; endl;
    }
};
</code></pre>
<h1>🔹 Cell Class</h1>
<pre><code class="language-macs">class Cell {
public:
    int row, col;
    Symbol* symbol;

    Cell(int r, int c) : row(r), col(c), symbol(nullptr) {}

    bool isEmpty() {
        return symbol == nullptr;
    }

    void setSymbol(Symbol* s) {
        symbol = s;
    }
};
</code></pre>
<h1>🔹 Board Class</h1>
<pre><code class="language-cpp">class Board {
private:
    int size;
    vector&lt;vector&lt;Cell&gt;&gt; grid;

public:
    Board(int n) : size(n) {
        for(int i=0;i&lt;n;i++) {
            vector&lt;Cell&gt; row;
            for(int j=0;j&lt;n;j++)
                row.emplace_back(i,j);
            grid.push_back(row);
        }
    }

    int getSize() { return size; }

    bool placeMove(int r, int c, Symbol* s) {
        if(r&lt;0 || c&lt;0 || r&gt;=size || c&gt;=size)
            return false;
        if(!grid[r][c].isEmpty())
            return false;

        grid[r][c].setSymbol(s);
        return true;
    }
};
</code></pre>
<h1>🔹 Strategy Pattern  Winning Strategy Base</h1>
<pre><code class="language-macs">class BaseWinningStrategy {
protected:
    int size;
public:
    BaseWinningStrategy(int n): size(n){}
    virtual bool checkWin(int row, int col, Symbol sym)=0;
    virtual ~BaseWinningStrategy(){}
};
</code></pre>
<h1>🔹 Efficient Winning Strategy (O(1))</h1>
<pre><code class="language-cpp">class EfficientWinningStrategy : public BaseWinningStrategy {
private:
    vector&lt;int&gt; rowCount;
    vector&lt;int&gt; colCount;
    int diag=0, antiDiag=0;

public:
    EfficientWinningStrategy(int n)
        : BaseWinningStrategy(n),
          rowCount(n,0), colCount(n,0) {}

    bool checkWin(int row, int col, Symbol sym) override {
        int val = (int)sym;

        rowCount[row]+=val;
        colCount[col]+=val;

        if(row==col) diag+=val;
        if(row+col==size-1) antiDiag+=val;

        if(abs(rowCount[row])==size ||
           abs(colCount[col])==size ||
           abs(diag)==size ||
           abs(antiDiag)==size)
            return true;

        return false;
    }
};
</code></pre>
<h1>🔹 Factory Method  Player Creation</h1>
<pre><code class="language-cpp">class Player {
protected:
    string name;
    Symbol symbol;

public:
    Player(string n, Symbol s): name(n), symbol(s){}
    virtual pair&lt;int,int&gt; makeMove()=0;
    Symbol getSymbol(){ return symbol; }
    string getName(){ return name; }
    virtual ~Player(){}
};

class HumanPlayer : public Player {
public:
    HumanPlayer(string n, Symbol s)
        : Player(n,s){}

    pair&lt;int,int&gt; makeMove() override {
        int r,c;
        cout&lt;&lt;"Enter row and col: ";
        cin&gt;&gt;r&gt;&gt;c;
        return {r,c};
    }
};

class PlayerFactory {
public:
    static shared_ptr&lt;Player&gt; createPlayer(
        string type, string name, Symbol s) {
        if(type=="HUMAN")
            return make_shared&lt;HumanPlayer&gt;(name,s);
        return nullptr;
    }
};
</code></pre>
<h1>🔹 Decorator Pattern  AI Extension</h1>
<pre><code class="language-cpp">class PlayerDecorator : public Player {
protected:
    shared_ptr&lt;Player&gt; player;
public:
    PlayerDecorator(shared_ptr&lt;Player&gt; p)
        : Player(p-&gt;getName(), p-&gt;getSymbol()),
          player(p) {}
};

class AIPlayerDecorator : public PlayerDecorator {
public:
    AIPlayerDecorator(shared_ptr&lt;Player&gt; p)
        : PlayerDecorator(p){}

    pair&lt;int,int&gt; makeMove() override {
        cout&lt;&lt;"AI making move...\n";
        return {0,0}; 
    }
};
</code></pre>
<h1>🔹 Game Class</h1>
<pre><code class="language-cpp">class Game {
private:
    Board board;
    shared_ptr&lt;Player&gt; p1;
    shared_ptr&lt;Player&gt; p2;
    shared_ptr&lt;Player&gt; current;
    unique_ptr&lt;BaseWinningStrategy&gt; strategy;
    GameStatus status;
    int moves=0;

public:
    Game(int n,
         shared_ptr&lt;Player&gt; pl1,
         shared_ptr&lt;Player&gt; pl2)
        : board(n), p1(pl1), p2(pl2),
          current(pl1),
          strategy(make_unique&lt;EfficientWinningStrategy&gt;(n)),
          status(GameStatus::IN_PROGRESS) {}

    void play() {

        while(status==GameStatus::IN_PROGRESS) {

            auto move=current-&gt;makeMove();
            bool placed=board.placeMove(
                move.first, move.second,
                &amp;current-&gt;getSymbol());

            if(!placed){
                cout&lt;&lt;"Invalid Move\n";
                continue;
            }

            Logger::getInstance().update(
                current-&gt;getName()+" moved");

            moves++;

            if(strategy-&gt;checkWin(
                move.first, move.second,
                current-&gt;getSymbol())) {

                status=GameStatus::WIN;
                cout&lt;&lt;current-&gt;getName()&lt;&lt;" Wins!\n";
                break;
            }

            if(moves==board.getSize()*board.getSize()){
                status=GameStatus::DRAW;
                cout&lt;&lt;"Game Draw\n";
                break;
            }

            current=(current==p1? p2:p1);
        }
    }
};
</code></pre>
<h1>🔹 Builder Pattern  Game Builder</h1>
<pre><code class="language-cpp">class GameBuilder {
private:
    int size;
    shared_ptr&lt;Player&gt; p1;
    shared_ptr&lt;Player&gt; p2;

public:
    GameBuilder&amp; setSize(int n){
        size=n;
        return *this;
    }

    GameBuilder&amp; setPlayer1(shared_ptr&lt;Player&gt; pl){
        p1=pl;
        return *this;
    }

    GameBuilder&amp; setPlayer2(shared_ptr&lt;Player&gt; pl){
        p2=pl;
        return *this;
    }

    unique_ptr&lt;Game&gt; build(){
        return make_unique&lt;Game&gt;(size,p1,p2);
    }
};
</code></pre>
<h1>🔹 Main Function</h1>
<pre><code class="language-cpp">int main(){

    auto player1=PlayerFactory::createPlayer(
        "HUMAN","Alice",Symbol::X);

    auto player2=PlayerFactory::createPlayer(
        "HUMAN","Bob",Symbol::O);

    auto game=GameBuilder()
                .setSize(3)
                .setPlayer1(player1)
                .setPlayer2(player2)
                .build();

    game-&gt;play();

    return 0;
}
</code></pre>
<h1>📌 Complexity Analysis</h1>
<table>
<thead>
<tr>
<th>Operation</th>
<th>Complexity</th>
</tr>
</thead>
<tbody><tr>
<td>Move Placement</td>
<td>O(1)</td>
</tr>
<tr>
<td>Win Check</td>
<td>O(1)</td>
</tr>
<tr>
<td>Draw Check</td>
<td>O(1)</td>
</tr>
<tr>
<td>Space</td>
<td>O(n)</td>
</tr>
</tbody></table>
<h1>🧵 Multithreading Problems in the Tic Tac Toe Implementation</h1>
<p>Our current implementation is <strong>single-threaded</strong> and assumes:</p>
<ul>
<li><p>Only one thread calls <code>game-&gt;play()</code></p>
</li>
<li><p>Only one thread makes moves</p>
</li>
<li><p>No external UI thread</p>
</li>
<li><p>No AI thread</p>
</li>
<li><p>No logging concurrency</p>
</li>
</ul>
<p>If we allow:</p>
<ul>
<li><p>Multiple threads (UI thread + AI thread)</p>
</li>
<li><p>Network multiplayer</p>
</li>
<li><p>Async logging</p>
</li>
<li><p>Spectator updates</p>
</li>
</ul>
<p>👉 The current design becomes unsafe.</p>
<p>Below is a <strong>complete breakdown of every multithreading issue</strong> and its proper fix.</p>
<h1>🚨 PROBLEM 1: Race Condition on Board State</h1>
<h3>Where?</h3>
<pre><code class="language-macs">bool placeMove(int r, int c, Symbol* s)
</code></pre>
<p>Two threads:</p>
<p>Thread A: places move at (0,0) Thread B: places move at (0,0)</p>
<p>Both check:</p>
<pre><code class="language-macs">if(!grid[r][c].isEmpty())
</code></pre>
<p>Both see empty Both write Result: corrupted state </p>
<h3><strong> Solution: covered in</strong> <a href="https://interview.lldcoding.com/dashboard/lld-cpp-course1?chapter=Tic-Tac-Toe-L2FwaS9jb250ZW50L2xsZC1jcHAtY291cnNlLVRpYy1UYWMtVG9lLmNodW5rMC5lbmNyeXB0ZWQ%3D"><strong>our course</strong></a><strong>.</strong></h3>
<h1>🚨 PROBLEM 2: Race Condition in Winning Strategy Counters</h1>
<p>In <code>EfficientWinningStrategy</code>:</p>
<pre><code class="language-macs">rowCount[row] += val;
colCount[col] += val;
diag += val;
</code></pre>
<p>Two threads updating simultaneously  lost updates.</p>
<p>Example:</p>
<p>Thread A: rowCount[0] = 1 Thread B: rowCount[0] = 1 Final: 1 (should be 2)</p>
<h3> Solution : <strong>covered in</strong> <a href="https://interview.lldcoding.com/dashboard/lld-cpp-course1?chapter=Tic-Tac-Toe-L2FwaS9jb250ZW50L2xsZC1jcHAtY291cnNlLVRpYy1UYWMtVG9lLmNodW5rMC5lbmNyeXB0ZWQ%3D"><strong>our course</strong></a><strong>.</strong></h3>
<h1>🚨 PROBLEM 3: Race Condition on <code>moves</code> Counter</h1>
<p>In Game class:</p>
<pre><code class="language-macs">moves++;
</code></pre>
<p>Two threads increment  lost update.</p>
<h3> Fix: <strong>covered in</strong> <a href="https://interview.lldcoding.com/dashboard/lld-cpp-course1?chapter=Tic-Tac-Toe-L2FwaS9jb250ZW50L2xsZC1jcHAtY291cnNlLVRpYy1UYWMtVG9lLmNodW5rMC5lbmNyeXB0ZWQ%3D"><strong>our course</strong></a><strong>.</strong></h3>
<h1>🚨 PROBLEM 4: Race Condition on <code>current</code> Player Switch</h1>
<pre><code class="language-macs">current = (current==p1? p2:p1);
</code></pre>
<p>If two threads call play logic:</p>
<ul>
<li><p>Player may switch twice</p>
</li>
<li><p>Wrong turn execution</p>
</li>
<li><p>Inconsistent state</p>
</li>
</ul>
<h3> Fix: <strong>covered in</strong> <a href="https://interview.lldcoding.com/dashboard/lld-cpp-course1?chapter=Tic-Tac-Toe-L2FwaS9jb250ZW50L2xsZC1jcHAtY291cnNlLVRpYy1UYWMtVG9lLmNodW5rMC5lbmNyeXB0ZWQ%3D"><strong>our course</strong></a><strong>.</strong></h3>
<h1>🚨 PROBLEM 5: Logger Output Interleaving</h1>
<pre><code class="language-macs">cout &lt;&lt; "[LOG] ...";
</code></pre>
<p>Two threads log simultaneously:</p>
<p>Output becomes:</p>
<pre><code class="language-plaintext">[LOG] Alice m[LOG] Bob moved
oved
</code></pre>
<h3> Fix: <strong>covered in</strong> <a href="https://interview.lldcoding.com/dashboard/lld-cpp-course1?chapter=Tic-Tac-Toe-L2FwaS9jb250ZW50L2xsZC1jcHAtY291cnNlLVRpYy1UYWMtVG9lLmNodW5rMC5lbmNyeXB0ZWQ%3D"><strong>our course</strong></a><strong>.</strong></h3>
<h1>🚨 PROBLEM 6: Deadlock Risk</h1>
<p>If:</p>
<ul>
<li><p>Board mutex</p>
</li>
<li><p>Strategy mutex</p>
</li>
<li><p>Game mutex</p>
</li>
</ul>
<p>Are locked in different order across threads  deadlock.</p>
<h3> Fix: <strong>covered in</strong> <a href="https://interview.lldcoding.com/dashboard/lld-cpp-course1?chapter=Tic-Tac-Toe-L2FwaS9jb250ZW50L2xsZC1jcHAtY291cnNlLVRpYy1UYWMtVG9lLmNodW5rMC5lbmNyeXB0ZWQ%3D"><strong>our course</strong></a><strong>.</strong></h3>
<h2>🚨 PROBLEM 7: Check-Then-Act Race</h2>
<p>Example:</p>
<pre><code class="language-macs">if(!placed)
    continue;

if(strategy-&gt;checkWin(...))
</code></pre>
<p>If two threads process same turn  invalid.</p>
<hr />
<h3> Fix: <strong>covered in</strong> <a href="https://interview.lldcoding.com/dashboard/lld-cpp-course1?chapter=Tic-Tac-Toe-L2FwaS9jb250ZW50L2xsZC1jcHAtY291cnNlLVRpYy1UYWMtVG9lLmNodW5rMC5lbmNyeXB0ZWQ%3D"><strong>our course</strong></a><strong>.</strong></h3>
<h1>🚨 PROBLEM 8: AI Thread vs Human Thread</h1>
<p>If AI runs in separate thread:</p>
<ul>
<li><p>Both may place move simultaneously</p>
</li>
<li><p>Breaks turn logic</p>
</li>
</ul>
<h3> Solution: <strong>covered in</strong> <a href="https://interview.lldcoding.com/dashboard/lld-cpp-course1?chapter=Tic-Tac-Toe-L2FwaS9jb250ZW50L2xsZC1jcHAtY291cnNlLVRpYy1UYWMtVG9lLmNodW5rMC5lbmNyeXB0ZWQ%3D"><strong>our course</strong></a><strong>.</strong></h3>
<h1>🚨 PROBLEM 9: Memory Visibility Issue</h1>
<p>Without synchronization:</p>
<p>Thread A updates board Thread B may not see updated state (CPU cache issue)</p>
<h3> Solution: <strong>covered in</strong> <a href="https://interview.lldcoding.com/dashboard/lld-cpp-course1?chapter=Tic-Tac-Toe-L2FwaS9jb250ZW50L2xsZC1jcHAtY291cnNlLVRpYy1UYWMtVG9lLmNodW5rMC5lbmNyeXB0ZWQ%3D"><strong>our course</strong></a><strong>.</strong></h3>
<h1>🚨 PROBLEM 10: Builder Not Thread-Safe</h1>
<p>If multiple threads call:</p>
<pre><code class="language-macs">GameBuilder builder;
builder.setSize(3);
</code></pre>
<p>Shared builder instance  race.</p>
<h3> Fix: <strong>covered in</strong> <a href="https://interview.lldcoding.com/dashboard/lld-cpp-course1?chapter=Tic-Tac-Toe-L2FwaS9jb250ZW50L2xsZC1jcHAtY291cnNlLVRpYy1UYWMtVG9lLmNodW5rMC5lbmNyeXB0ZWQ%3D"><strong>our course</strong></a><strong>.</strong></h3>
]]></description><link>https://lldcoding.com/design-lld-tic-tac-toe-c</link><guid isPermaLink="true">https://lldcoding.com/design-lld-tic-tac-toe-c</guid><category><![CDATA[Programming Blogs]]></category><category><![CDATA[Java]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[LLD]]></category><category><![CDATA[interview]]></category><category><![CDATA[System Design]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[Python]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[programming languages]]></category><dc:creator><![CDATA[Subhahu Jain]]></dc:creator></item><item><title><![CDATA[Design (LLD) Rate Limiter - C++]]></title><description><![CDATA[<h1>📌 1. Functional Requirements</h1>
<p>A Rate Limiter system should:</p>
<ul>
<li><p>Limit requests per <strong>client/user</strong></p>
</li>
<li><p>Support multiple rate limiting algorithms</p>
</li>
<li><p>Allow dynamic algorithm switching</p>
</li>
<li><p>Support different limits per client</p>
</li>
<li><p>Return <strong>Allow / Deny</strong> decision</p>
</li>
<li><p>Track usage statistics</p>
</li>
<li><p>Log rate limit violations</p>
</li>
<li><p>Be extensible for distributed systems</p>
</li>
</ul>
<h1>📌 2. Non-Functional Requirements</h1>
<ul>
<li><p>High performance (O(1) where possible)</p>
</li>
<li><p>Extensible architecture</p>
</li>
<li><p>Clean separation of concerns</p>
</li>
<li><p>Algorithm pluggability</p>
</li>
<li><p>Easy to test</p>
</li>
</ul>
<h1>📌 3. Supported Algorithms</h1>
<p>We implement <strong>four major algorithms</strong>:</p>
<h2>1 Fixed Window Counter</h2>
<p><strong>Idea:</strong> Allow N requests per time window.</p>
<pre><code class="language-plaintext">Example:
Limit = 3 requests
Window = 10 seconds
</code></pre>
<p>After 3 requests  deny until window resets.</p>
<h3> Complexity</h3>
<ul>
<li><p>Time: O(1)</p>
</li>
<li><p>Space: O(n clients)</p>
</li>
</ul>
<h2>2 Sliding Window Log</h2>
<p><strong>Idea:</strong> Store timestamps of each request.</p>
<p>Before allowing:</p>
<ul>
<li><p>Remove old timestamps</p>
</li>
<li><p>Check remaining count</p>
</li>
</ul>
<h3> Complexity</h3>
<ul>
<li><p>Time: O(k) (k = requests in window)</p>
</li>
<li><p>Space: O(n  k)</p>
</li>
</ul>
<h2>3 Token Bucket</h2>
<p><strong>Idea:</strong></p>
<ul>
<li><p>Tokens refill over time</p>
</li>
<li><p>Each request consumes 1 token</p>
</li>
<li><p>If no token  deny</p>
</li>
</ul>
<h3> Complexity</h3>
<ul>
<li><p>Time: O(1)</p>
</li>
<li><p>Space: O(n)</p>
</li>
</ul>
<h2>4 Leaky Bucket</h2>
<p><strong>Idea:</strong></p>
<ul>
<li><p>Requests enter queue</p>
</li>
<li><p>Requests leak at constant rate</p>
</li>
<li><p>If queue full  deny</p>
</li>
</ul>
<h3> Complexity</h3>
<ul>
<li><p>Time: O(1)</p>
</li>
<li><p>Space: O(n  k)</p>
</li>
</ul>
<h1>📌 4. Design Patterns Used</h1>
<table>
<thead>
<tr>
<th>Pattern</th>
<th>Where Used</th>
<th>Why</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Strategy</strong></td>
<td>Algorithms</td>
<td>Switch rate limiting strategy dynamically</td>
</tr>
<tr>
<td><strong>Factory Method</strong></td>
<td>Create limiter</td>
<td>Encapsulate creation logic</td>
</tr>
<tr>
<td><strong>Singleton</strong></td>
<td>Manager</td>
<td>One global configuration</td>
</tr>
<tr>
<td><strong>Observer</strong></td>
<td>Logging</td>
<td>Notify on rate limit exceed</td>
</tr>
<tr>
<td><strong>Decorator</strong></td>
<td>Logging wrapper</td>
<td>Add behavior without modifying core</td>
</tr>
<tr>
<td><strong>Builder</strong></td>
<td>Config creation</td>
<td>Clean configuration building</td>
</tr>
<tr>
<td><strong>Repository</strong></td>
<td>Client storage</td>
<td>Abstract client data layer</td>
</tr>
<tr>
<td><strong>Command</strong></td>
<td>Request execution</td>
<td>Encapsulate request action</td>
</tr>
<tr>
<td><strong>Template Method</strong></td>
<td>BaseRateLimiter</td>
<td>Standardize flow</td>
</tr>
</tbody></table>
<h1>📌 5. Class Design</h1>
<pre><code class="language-mermaid">classDiagram
    class Observer {
        &lt;&lt;abstract&gt;&gt;
        +update(string message) void
    }
    class Logger {
        +update(string message) void
    }
    Observer &lt;|-- Logger

    class RateLimiterConfig {
        +int limit
        +int windowSize
    }

    class RateLimiterConfigBuilder {
        -RateLimiterConfig config
        +setLimit(int) Builder
        +setWindowSize(int) Builder
        +build() RateLimiterConfig
    }
    RateLimiterConfigBuilder --&gt; RateLimiterConfig : creates

    class BaseRateLimiter {
        &lt;&lt;abstract&gt;&gt;
        #RateLimiterConfig config
        +BaseRateLimiter(RateLimiterConfig cfg)
        +allowRequest(string id) bool
        +process(string id) bool
    }
    BaseRateLimiter *-- RateLimiterConfig : contains

    class FixedWindowLimiter {
        -Map_Counter counter
        +process(string id) bool
    }
    BaseRateLimiter &lt;|-- FixedWindowLimiter

    class SlidingWindowLimiter {
        -Map_Logs logs
        +process(string id) bool
    }
    BaseRateLimiter &lt;|-- SlidingWindowLimiter

    class TokenBucketLimiter {
        -Map_Buckets buckets
        +process(string id) bool
    }
    BaseRateLimiter &lt;|-- TokenBucketLimiter

    class LeakyBucketLimiter {
        -Map_Buckets buckets
        +process(string id) bool
    }
    BaseRateLimiter &lt;|-- LeakyBucketLimiter

    class RateLimiterFactory {
        +createLimiter(string type, Config cfg) BaseLimiter
    }
    RateLimiterFactory --&gt; BaseRateLimiter : creates

    class RateLimiterDecorator {
        #BaseLimiter limiter
        +RateLimiterDecorator(BaseLimiter l)
    }
    BaseRateLimiter &lt;|-- RateLimiterDecorator
    RateLimiterDecorator o-- BaseRateLimiter : decorates

    class LoggingDecorator {
        -Observer observer
        +LoggingDecorator(BaseLimiter l, Observer obs)
        +process(string id) bool
    }
    RateLimiterDecorator &lt;|-- LoggingDecorator
    LoggingDecorator --&gt; Observer : notifies

    class ClientRepository {
        -Map_Clients clients
        +addClient(string id) void
        +exists(string id) bool
    }

    class Command {
        &lt;&lt;abstract&gt;&gt;
        +execute() void
    }
    class RequestCommand {
        -BaseLimiter limiter
        -string id
        +RequestCommand(BaseLimiter l, string id)
        +execute() void
    }
    Command &lt;|-- RequestCommand
    RequestCommand --&gt; BaseRateLimiter : uses

    class RateLimiterManager {
        -BaseLimiter limiter
        -RateLimiterManager()
        +getInstance() Manager
        +setLimiter(BaseLimiter l) void
        +getLimiter() BaseLimiter
    }
    RateLimiterManager o-- BaseRateLimiter : holds
</code></pre>
<h1>📌 6. Complete C++ Implementation (Single Threaded)</h1>
<blockquote>
<p> This is intentionally single-threaded for machine coding clarity.</p>
</blockquote>
<h2>🔹 1. Observer Pattern (Logger)</h2>
<pre><code class="language-cpp">class Observer {
public:
    virtual void update(string message) = 0;
    virtual ~Observer() {}
};

class Logger : public Observer {
public:
    void update(string message) override {
        cout &lt;&lt; "[LOG]: " &lt;&lt; message &lt;&lt; endl;
    }
};
</code></pre>
<h2>🔹 2. Builder Pattern (Configuration)</h2>
<pre><code class="language-cpp">class RateLimiterConfig {
public:
    int limit;
    int windowSize;
};

class RateLimiterConfigBuilder {
private:
    RateLimiterConfig config;

public:
    RateLimiterConfigBuilder&amp; setLimit(int l) {
        config.limit = l;
        return *this;
    }

    RateLimiterConfigBuilder&amp; setWindowSize(int w) {
        config.windowSize = w;
        return *this;
    }

    RateLimiterConfig build() {
        return config;
    }
};
</code></pre>
<h2>🔹 3. Template Method Pattern</h2>
<pre><code class="language-cpp">class BaseRateLimiter {
protected:
    RateLimiterConfig config;

public:
    BaseRateLimiter(RateLimiterConfig cfg) : config(cfg) {}

    bool allowRequest(string clientId) {
        return process(clientId);
    }

    virtual bool process(string clientId) = 0;
    virtual ~BaseRateLimiter() {}
};
</code></pre>
<h1>📌 7. Strategy Pattern (All Algorithms)</h1>
<h2>🔹 Fixed Window</h2>
<pre><code class="language-cpp">class FixedWindowLimiter : public BaseRateLimiter {
private:
    unordered_map&lt;string, pair&lt;int, time_t&gt;&gt; counter;

public:
    FixedWindowLimiter(RateLimiterConfig cfg)
        : BaseRateLimiter(cfg) {}

    bool process(string clientId) override {
        time_t now = time(nullptr);

        if(counter[clientId].second + config.windowSize &lt;= now) {
            counter[clientId] = {1, now};
            return true;
        }

        if(counter[clientId].first &lt; config.limit) {
            counter[clientId].first++;
            return true;
        }

        return false;
    }
};
</code></pre>
<h2>🔹 Sliding Window</h2>
<pre><code class="language-cpp">class SlidingWindowLimiter : public BaseRateLimiter {
private:
    unordered_map&lt;string, vector&lt;time_t&gt;&gt; logs;

public:
    SlidingWindowLimiter(RateLimiterConfig cfg)
        : BaseRateLimiter(cfg) {}

    bool process(string clientId) override {
        time_t now = time(nullptr);
        auto&amp; timestamps = logs[clientId];

        timestamps.erase(remove_if(timestamps.begin(), timestamps.end(),
            [&amp;](time_t t) { return t &lt;= now - config.windowSize; }),
            timestamps.end());

        if(timestamps.size() &lt; config.limit) {
            timestamps.push_back(now);
            return true;
        }

        return false;
    }
};
</code></pre>
<h2>🔹 Token Bucket</h2>
<pre><code class="language-cpp">class TokenBucketLimiter : public BaseRateLimiter {
private:
    struct Bucket {
        int tokens = 0;
        time_t lastRefill = 0;
    };

    unordered_map&lt;string, Bucket&gt; buckets;

public:
    TokenBucketLimiter(RateLimiterConfig cfg)
        : BaseRateLimiter(cfg) {}

    bool process(string clientId) override {
        time_t now = time(nullptr);
        auto&amp; bucket = buckets[clientId];

        if(bucket.tokens == 0) {
            bucket.tokens = config.limit;
            bucket.lastRefill = now;
        }

        int refill = now - bucket.lastRefill;
        if(refill &gt; 0) {
            bucket.tokens = min(config.limit, bucket.tokens + refill);
            bucket.lastRefill = now;
        }

        if(bucket.tokens &gt; 0) {
            bucket.tokens--;
            return true;
        }

        return false;
    }
};
</code></pre>
<h2>🔹 Leaky Bucket</h2>
<pre><code class="language-cpp">class LeakyBucketLimiter : public BaseRateLimiter {
private:
    struct Bucket {
        queue&lt;time_t&gt; requests;
    };

    unordered_map&lt;string, Bucket&gt; buckets;

public:
    LeakyBucketLimiter(RateLimiterConfig cfg)
        : BaseRateLimiter(cfg) {}

    bool process(string clientId) override {
        time_t now = time(nullptr);
        auto&amp; bucket = buckets[clientId];

        while(!bucket.requests.empty() &amp;&amp;
              bucket.requests.front() &lt;= now - config.windowSize) {
            bucket.requests.pop();
        }

        if(bucket.requests.size() &lt; config.limit) {
            bucket.requests.push(now);
            return true;
        }

        return false;
    }
};
</code></pre>
<h1>📌 8. Factory Pattern</h1>
<pre><code class="language-cpp">class RateLimiterFactory {
public:
    static shared_ptr&lt;BaseRateLimiter&gt; createLimiter(
        string type, RateLimiterConfig config) {

        if(type == "FIXED")
            return make_shared&lt;FixedWindowLimiter&gt;(config);
        if(type == "SLIDING")
            return make_shared&lt;SlidingWindowLimiter&gt;(config);
        if(type == "TOKEN")
            return make_shared&lt;TokenBucketLimiter&gt;(config);
        if(type == "LEAKY")
            return make_shared&lt;LeakyBucketLimiter&gt;(config);

        return nullptr;
    }
};
</code></pre>
<h1>📌 9. Decorator Pattern (Logging)</h1>
<pre><code class="language-cpp">class RateLimiterDecorator : public BaseRateLimiter {
protected:
    shared_ptr&lt;BaseRateLimiter&gt; limiter;

public:
    RateLimiterDecorator(shared_ptr&lt;BaseRateLimiter&gt; l)
        : BaseRateLimiter(l-&gt;config), limiter(l) {}
};

class LoggingDecorator : public RateLimiterDecorator {
private:
    Observer* observer;

public:
    LoggingDecorator(shared_ptr&lt;BaseRateLimiter&gt; l, Observer* obs)
        : RateLimiterDecorator(l), observer(obs) {}

    bool process(string clientId) override {
        bool allowed = limiter-&gt;allowRequest(clientId);

        if(!allowed)
            observer-&gt;update("Rate limit exceeded for: " + clientId);

        return allowed;
    }
};
</code></pre>
<h1>📌 10. Repository Pattern</h1>
<pre><code class="language-cpp">class ClientRepository {
private:
    unordered_map&lt;string, int&gt; clients;

public:
    void addClient(string id) {
        clients[id] = 1;
    }

    bool exists(string id) {
        return clients.count(id);
    }
};
</code></pre>
<h1>📌 11. Command Pattern</h1>
<pre><code class="language-cpp">class Command {
public:
    virtual void execute() = 0;
    virtual ~Command() {}
};

class RequestCommand : public Command {
private:
    shared_ptr&lt;BaseRateLimiter&gt; limiter;
    string clientId;

public:
    RequestCommand(shared_ptr&lt;BaseRateLimiter&gt; l, string id)
        : limiter(l), clientId(id) {}

    void execute() override {
        bool allowed = limiter-&gt;allowRequest(clientId);
        cout &lt;&lt; "Request for " &lt;&lt; clientId
             &lt;&lt; (allowed ? " Allowed" : " Denied") &lt;&lt; endl;
    }
};
</code></pre>
<h1>📌 12. Singleton Manager</h1>
<pre><code class="language-cpp">class RateLimiterManager {
private:
    shared_ptr&lt;BaseRateLimiter&gt; limiter;

    RateLimiterManager() {}

public:
    static RateLimiterManager&amp; getInstance() {
        static RateLimiterManager instance;
        return instance;
    }

    void setLimiter(shared_ptr&lt;BaseRateLimiter&gt; l) {
        limiter = l;
    }

    shared_ptr&lt;BaseRateLimiter&gt; getLimiter() {
        return limiter;
    }
};
</code></pre>
<h1>📌 13. Main Function</h1>
<pre><code class="language-cpp">int main() {

    RateLimiterConfig config =
        RateLimiterConfigBuilder()
            .setLimit(3)
            .setWindowSize(10)
            .build();

    auto limiter = RateLimiterFactory::createLimiter("SLIDING", config);

    Logger logger;
    auto decoratedLimiter =
        make_shared&lt;LoggingDecorator&gt;(limiter, &amp;logger);

    RateLimiterManager::getInstance().setLimiter(decoratedLimiter);

    string client = "clientA";

    for(int i = 0; i &lt; 5; i++) {
        RequestCommand cmd(
            RateLimiterManager::getInstance().getLimiter(),
            client
        );
        cmd.execute();
    }

    return 0;
}
</code></pre>
<h3>Complete running code</h3>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;unordered_map&gt;
#include &lt;queue&gt;
#include &lt;vector&gt;
#include &lt;memory&gt;
#include &lt;ctime&gt;

using namespace std;

//////////////////////////////////////////////////////////////
// OBSERVER PATTERN
//////////////////////////////////////////////////////////////

class Observer {
public:
    virtual void update(string message) = 0;
    virtual ~Observer() {}
};

class Logger : public Observer {
public:
    void update(string message) override {
        cout &lt;&lt; "[LOG]: " &lt;&lt; message &lt;&lt; endl;
    }
};

//////////////////////////////////////////////////////////////
// BUILDER PATTERN
//////////////////////////////////////////////////////////////

class RateLimiterConfig {
public:
    int limit;
    int windowSize;
};

class RateLimiterConfigBuilder {
private:
    RateLimiterConfig config;

public:
    RateLimiterConfigBuilder&amp; setLimit(int l) {
        config.limit = l;
        return *this;
    }

    RateLimiterConfigBuilder&amp; setWindowSize(int w) {
        config.windowSize = w;
        return *this;
    }

    RateLimiterConfig build() {
        return config;
    }
};

//////////////////////////////////////////////////////////////
// TEMPLATE METHOD PATTERN
//////////////////////////////////////////////////////////////

class BaseRateLimiter {
protected:
    RateLimiterConfig config;

public:
    BaseRateLimiter(RateLimiterConfig cfg) : config(cfg) {}

    bool allowRequest(string clientId) {
        return process(clientId);
    }

    virtual bool process(string clientId) = 0;
    virtual ~BaseRateLimiter() {}
};

//////////////////////////////////////////////////////////////
// STRATEGY PATTERN (Algorithms)
//////////////////////////////////////////////////////////////

class FixedWindowLimiter : public BaseRateLimiter {
private:
    unordered_map&lt;string, pair&lt;int, time_t&gt;&gt; counter;

public:
    FixedWindowLimiter(RateLimiterConfig cfg)
        : BaseRateLimiter(cfg) {}

    bool process(string clientId) override {
        time_t now = time(nullptr);

        if(counter[clientId].second + config.windowSize &lt;= now) {
            counter[clientId] = {1, now};
            return true;
        }

        if(counter[clientId].first &lt; config.limit) {
            counter[clientId].first++;
            return true;
        }

        return false;
    }
};

class SlidingWindowLimiter : public BaseRateLimiter {
private:
    unordered_map&lt;string, vector&lt;time_t&gt;&gt; logs;

public:
    SlidingWindowLimiter(RateLimiterConfig cfg)
        : BaseRateLimiter(cfg) {}

    bool process(string clientId) override {
        time_t now = time(nullptr);
        auto&amp; timestamps = logs[clientId];

        timestamps.erase(remove_if(timestamps.begin(), timestamps.end(),
            [&amp;](time_t t) { return t &lt;= now - config.windowSize; }),
            timestamps.end());

        if(timestamps.size() &lt; config.limit) {
            timestamps.push_back(now);
            return true;
        }

        return false;
    }
};

class TokenBucketLimiter : public BaseRateLimiter {
private:
    struct Bucket {
        int tokens;
        time_t lastRefill;
    };

    unordered_map&lt;string, Bucket&gt; buckets;

public:
    TokenBucketLimiter(RateLimiterConfig cfg)
        : BaseRateLimiter(cfg) {}

    bool process(string clientId) override {
        time_t now = time(nullptr);
        auto&amp; bucket = buckets[clientId];

        if(bucket.tokens == 0) {
            bucket.tokens = config.limit;
            bucket.lastRefill = now;
        }

        int refill = (now - bucket.lastRefill);
        if(refill &gt; 0) {
            bucket.tokens = min(config.limit, bucket.tokens + refill);
            bucket.lastRefill = now;
        }

        if(bucket.tokens &gt; 0) {
            bucket.tokens--;
            return true;
        }

        return false;
    }
};

class LeakyBucketLimiter : public BaseRateLimiter {
private:
    struct Bucket {
        queue&lt;time_t&gt; requests;
    };

    unordered_map&lt;string, Bucket&gt; buckets;

public:
    LeakyBucketLimiter(RateLimiterConfig cfg)
        : BaseRateLimiter(cfg) {}

    bool process(string clientId) override {
        time_t now = time(nullptr);
        auto&amp; bucket = buckets[clientId];

        while(!bucket.requests.empty() &amp;&amp;
              bucket.requests.front() &lt;= now - config.windowSize) {
            bucket.requests.pop();
        }

        if(bucket.requests.size() &lt; config.limit) {
            bucket.requests.push(now);
            return true;
        }

        return false;
    }
};

//////////////////////////////////////////////////////////////
// FACTORY METHOD
//////////////////////////////////////////////////////////////

class RateLimiterFactory {
public:
    static shared_ptr&lt;BaseRateLimiter&gt; createLimiter(
        string type, RateLimiterConfig config) {

        if(type == "FIXED")
            return make_shared&lt;FixedWindowLimiter&gt;(config);
        if(type == "SLIDING")
            return make_shared&lt;SlidingWindowLimiter&gt;(config);
        if(type == "TOKEN")
            return make_shared&lt;TokenBucketLimiter&gt;(config);
        if(type == "LEAKY")
            return make_shared&lt;LeakyBucketLimiter&gt;(config);

        return nullptr;
    }
};

//////////////////////////////////////////////////////////////
// DECORATOR PATTERN (Logging)
//////////////////////////////////////////////////////////////

class RateLimiterDecorator : public BaseRateLimiter {
protected:
    shared_ptr&lt;BaseRateLimiter&gt; limiter;

public:
    RateLimiterDecorator(shared_ptr&lt;BaseRateLimiter&gt; l)
        : BaseRateLimiter(l-&gt;config), limiter(l) {}
};

class LoggingDecorator : public RateLimiterDecorator {
private:
    Observer* observer;

public:
    LoggingDecorator(shared_ptr&lt;BaseRateLimiter&gt; l, Observer* obs)
        : RateLimiterDecorator(l), observer(obs) {}

    bool process(string clientId) override {
        bool allowed = limiter-&gt;allowRequest(clientId);

        if(!allowed)
            observer-&gt;update("Rate limit exceeded for: " + clientId);

        return allowed;
    }
};

//////////////////////////////////////////////////////////////
// REPOSITORY PATTERN
//////////////////////////////////////////////////////////////

class ClientRepository {
private:
    unordered_map&lt;string, int&gt; clients;

public:
    void addClient(string id) {
        clients[id] = 1;
    }

    bool exists(string id) {
        return clients.count(id);
    }
};

//////////////////////////////////////////////////////////////
// COMMAND PATTERN
//////////////////////////////////////////////////////////////

class Command {
public:
    virtual void execute() = 0;
    virtual ~Command() {}
};

class RequestCommand : public Command {
private:
    shared_ptr&lt;BaseRateLimiter&gt; limiter;
    string clientId;

public:
    RequestCommand(shared_ptr&lt;BaseRateLimiter&gt; l, string id)
        : limiter(l), clientId(id) {}

    void execute() override {
        bool allowed = limiter-&gt;allowRequest(clientId);
        cout &lt;&lt; "Request for " &lt;&lt; clientId
             &lt;&lt; (allowed ? " Allowed" : " Denied") &lt;&lt; endl;
    }
};

//////////////////////////////////////////////////////////////
// SINGLETON MANAGER
//////////////////////////////////////////////////////////////

class RateLimiterManager {
private:
    shared_ptr&lt;BaseRateLimiter&gt; limiter;

    RateLimiterManager() {}

public:
    static RateLimiterManager&amp; getInstance() {
        static RateLimiterManager instance;
        return instance;
    }

    void setLimiter(shared_ptr&lt;BaseRateLimiter&gt; l) {
        limiter = l;
    }

    shared_ptr&lt;BaseRateLimiter&gt; getLimiter() {
        return limiter;
    }
};

//////////////////////////////////////////////////////////////
// MAIN
//////////////////////////////////////////////////////////////

int main() {

    RateLimiterConfig config =
        RateLimiterConfigBuilder()
            .setLimit(3)
            .setWindowSize(10)
            .build();

    auto limiter = RateLimiterFactory::createLimiter("SLIDING", config);

    Logger logger;
    auto decoratedLimiter =
        make_shared&lt;LoggingDecorator&gt;(limiter, &amp;logger);

    RateLimiterManager::getInstance().setLimiter(decoratedLimiter);

    string client = "clientA";

    for(int i = 0; i &lt; 5; i++) {
        RequestCommand cmd(
            RateLimiterManager::getInstance().getLimiter(),
            client
        );
        cmd.execute();
    }

    return 0;
}
</code></pre>
<h1>📌 14. Complexity Summary</h1>
<table>
<thead>
<tr>
<th>Algorithm</th>
<th>Time</th>
<th>Space</th>
</tr>
</thead>
<tbody><tr>
<td>Fixed Window</td>
<td>O(1)</td>
<td>O(n)</td>
</tr>
<tr>
<td>Sliding Window</td>
<td>O(k)</td>
<td>O(nk)</td>
</tr>
<tr>
<td>Token Bucket</td>
<td>O(1)</td>
<td>O(n)</td>
</tr>
<tr>
<td>Leaky Bucket</td>
<td>O(1)</td>
<td>O(nk)</td>
</tr>
</tbody></table>
<h1>📌 15. Interview-Level Talking Points</h1>
<p> Why Strategy?  Switch algorithms dynamically</p>
<p> Why Template Method?  Standardize request flow</p>
<p> Why Decorator?  Add logging without modifying core</p>
<p> Why Builder?  Clean configuration</p>
<p> Why Factory?  Decouple creation</p>
<p> Why Singleton?  Global configuration control</p>
<h1>🚨 Multithreading Problems in the Above Rate Limiter Implementation</h1>
<p>Our current implementation is <strong>single-threaded</strong>.</p>
<p>If multiple threads call:</p>
<pre><code class="language-macs">allowRequest(clientId);
</code></pre>
<p>simultaneously  the system becomes <strong>unsafe</strong>.</p>
<p>Below is a <strong>complete breakdown</strong> of all concurrency problems and their proper solutions.</p>
<h2>🔴 PROBLEM 1: Data Race on <code>unordered_map</code></h2>
<h3>Where?</h3>
<p>In every algorithm:</p>
<pre><code class="language-macs">unordered_map&lt;string, ...&gt; logs;
unordered_map&lt;string, ...&gt; counter;
unordered_map&lt;string, Bucket&gt; buckets;
</code></pre>
<h3>Why Its Dangerous?</h3>
<p><code>unordered_map</code> is NOT thread-safe.</p>
<p>Two threads doing:</p>
<pre><code class="language-plaintext">logs[clientId]
</code></pre>
<p>can:</p>
<ul>
<li><p>Corrupt internal bucket structure</p>
</li>
<li><p>Cause undefined behavior</p>
</li>
<li><p>Crash program</p>
</li>
</ul>
<h2> Solution : covered in our <a href="https://interview.lldcoding.com/dashboard/lld-cpp-course1?chapter=Rate+Limiter-L2FwaS9jb250ZW50L2xsZC1jcHAtY291cnNlLVJhdGUgTGltaXRlci5jaHVuazAuZW5jcnlwdGVk">course</a></h2>
<h2>🔴 PROBLEM 2: Lost Update (Counter Increment Race)</h2>
<p>In Fixed Window:</p>
<pre><code class="language-macs">counter[clientId].first++;
</code></pre>
<p>Two threads:</p>
<p>Thread A reads 2 Thread B reads 2 Thread A writes 3 Thread B writes 3</p>
<p>Expected: 4 Actual: 3 </p>
<p>Classic <strong>lost update problem</strong>.</p>
<h2> Solution : covered in our <a href="https://interview.lldcoding.com/dashboard/lld-cpp-course1?chapter=Rate+Limiter-L2FwaS9jb250ZW50L2xsZC1jcHAtY291cnNlLVJhdGUgTGltaXRlci5jaHVuazAuZW5jcnlwdGVk">course</a></h2>
<h2>🔴 PROBLEM 3: Check-Then-Act Race (Sliding Window)</h2>
<pre><code class="language-macs">if(timestamps.size() &lt; config.limit) {
    timestamps.push_back(now);
}
</code></pre>
<p>Two threads:</p>
<p>Thread A checks size = 2 Thread B checks size = 2 Both push Limit = 3 Now size = 4 </p>
<h2> Solution : covered in our <a href="https://interview.lldcoding.com/dashboard/lld-cpp-course1?chapter=Rate+Limiter-L2FwaS9jb250ZW50L2xsZC1jcHAtY291cnNlLVJhdGUgTGltaXRlci5jaHVuazAuZW5jcnlwdGVk">course</a></h2>
<h2>🔴 PROBLEM 4: Token Bucket Race</h2>
<h2>In Token Bucket:</h2>
<pre><code class="language-macs">bucket.tokens--;
</code></pre>
<p>Two threads:</p>
<ul>
<li><p>Both see tokens = 1</p>
</li>
<li><p>Both decrement</p>
</li>
<li><p>tokens becomes -1 </p>
</li>
</ul>
<h2> Solution 4A: covered in our <a href="https://interview.lldcoding.com/dashboard/lld-cpp-course1?chapter=Rate+Limiter-L2FwaS9jb250ZW50L2xsZC1jcHAtY291cnNlLVJhdGUgTGltaXRlci5jaHVuazAuZW5jcnlwdGVk">course</a></h2>
<h2> Solution 4B (Better): covered in our <a href="https://interview.lldcoding.com/dashboard/lld-cpp-course1?chapter=Rate+Limiter-L2FwaS9jb250ZW50L2xsZC1jcHAtY291cnNlLVJhdGUgTGltaXRlci5jaHVuazAuZW5jcnlwdGVk">course</a></h2>
<h2>🔴 PROBLEM 5: Singleton Not Fully Safe (Configuration Change)</h2>
<h2>If one thread:</h2>
<pre><code class="language-macs">setLimiter(...)
</code></pre>
<p>While another thread:</p>
<pre><code class="language-macs">getLimiter()
</code></pre>
<p>Race condition possible.</p>
<h2> Solution: covered in our <a href="https://interview.lldcoding.com/dashboard/lld-cpp-course1?chapter=Rate+Limiter-L2FwaS9jb250ZW50L2xsZC1jcHAtY291cnNlLVJhdGUgTGltaXRlci5jaHVuazAuZW5jcnlwdGVk">course</a></h2>
<h2>🔴 PROBLEM 6: Logging Race (Observer Pattern)</h2>
<p>If multiple threads:</p>
<pre><code class="language-macs">observer-&gt;update(...)
</code></pre>
<p>Output may interleave:</p>
<pre><code class="language-plaintext">[LOG]: Rate limi[LOG]: Rate limit exceeded...
</code></pre>
<h2> Solution: covered in our <a href="https://interview.lldcoding.com/dashboard/lld-cpp-course1?chapter=Rate+Limiter-L2FwaS9jb250ZW50L2xsZC1jcHAtY291cnNlLVJhdGUgTGltaXRlci5jaHVuazAuZW5jcnlwdGVk">course</a></h2>
<h2>🔴 PROBLEM 7: Memory Reallocation Race (Vector Erase)</h2>
<p>In Sliding Window:</p>
<pre><code class="language-macs">timestamps.erase(...)
</code></pre>
<p>If two threads erase simultaneously:</p>
<ul>
<li><p>Iterator invalidation</p>
</li>
<li><p>Memory corruption</p>
</li>
</ul>
<h2> Solution: covered in our <a href="https://interview.lldcoding.com/dashboard/lld-cpp-course1?chapter=Rate+Limiter-L2FwaS9jb250ZW50L2xsZC1jcHAtY291cnNlLVJhdGUgTGltaXRlci5jaHVuazAuZW5jcnlwdGVk">course</a></h2>
<h2>🔴 PROBLEM 8: Global Lock Bottleneck</h2>
<p>If we use:</p>
<pre><code class="language-macs">std::mutex mtx;
</code></pre>
<p>One global lock  only one request processed at a time.</p>
<p>Not scalable.</p>
<h2> Solution: covered in our <a href="https://interview.lldcoding.com/dashboard/lld-cpp-course1?chapter=Rate+Limiter-L2FwaS9jb250ZW50L2xsZC1jcHAtY291cnNlLVJhdGUgTGltaXRlci5jaHVuazAuZW5jcnlwdGVk">course</a></h2>
<h2>🔴 PROBLEM 9: Deadlock Risk</h2>
<p>If:</p>
<ul>
<li><p>Manager lock</p>
</li>
<li><p>Algorithm lock</p>
</li>
<li><p>Logger lock</p>
</li>
</ul>
<p>And locking order differs  deadlock.</p>
<h2> Solution: covered in our <a href="https://interview.lldcoding.com/dashboard/lld-cpp-course1?chapter=Rate+Limiter-L2FwaS9jb250ZW50L2xsZC1jcHAtY291cnNlLVJhdGUgTGltaXRlci5jaHVuazAuZW5jcnlwdGVk">course</a></h2>
<h2>🔴 PROBLEM 10: Time Function Not Monotonic</h2>
<pre><code class="language-macs">time(nullptr)
</code></pre>
<p>If system clock changes  limiter breaks.</p>
<h2> Solution: covered in our <a href="https://interview.lldcoding.com/dashboard/lld-cpp-course1?chapter=Rate+Limiter-L2FwaS9jb250ZW50L2xsZC1jcHAtY291cnNlLVJhdGUgTGltaXRlci5jaHVuazAuZW5jcnlwdGVk">course</a></h2>
<p><em><strong>For Java LLD, visit</strong></em> - <a href="https://www.lldcoding.com/design-lld-rate-limiter-machine-coding">https://www.lldcoding.com/design-lld-rate-limiter-machine-coding</a></p>
]]></description><link>https://lldcoding.com/design-lld-rate-limiter-cpp</link><guid isPermaLink="true">https://lldcoding.com/design-lld-rate-limiter-cpp</guid><category><![CDATA[interview]]></category><category><![CDATA[LLD]]></category><category><![CDATA[System Design]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[Developer]]></category><category><![CDATA[General Programming]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Java]]></category><category><![CDATA[Object Oriented Programming]]></category><category><![CDATA[Python]]></category><category><![CDATA[software development]]></category><category><![CDATA[Software Engineering]]></category><dc:creator><![CDATA[Subhahu Jain]]></dc:creator></item><item><title><![CDATA[Design (LLD) Vending Machine - C++]]></title><description><![CDATA[<h1>1 Functional Requirements</h1>
<p>A vending machine should support:</p>
<ul>
<li><p>Add products</p>
</li>
<li><p>Add inventory (quantity)</p>
</li>
<li><p>Insert money (multiple denominations)</p>
</li>
<li><p>Select product</p>
</li>
<li><p>Dispense product</p>
</li>
<li><p>Return change</p>
</li>
<li><p>Cancel transaction</p>
</li>
<li><p>Handle insufficient balance</p>
</li>
<li><p>Handle out-of-stock</p>
</li>
<li><p>Maintain transaction states</p>
</li>
<li><p>Support different pricing strategies</p>
</li>
<li><p>Notify user for events</p>
</li>
</ul>
<h1>2 Core Entities</h1>
<ul>
<li><p>Product</p>
</li>
<li><p>InventorySlot</p>
</li>
<li><p>VendingMachine</p>
</li>
<li><p>Transaction</p>
</li>
<li><p>Payment</p>
</li>
<li><p>ChangeDispenser</p>
</li>
<li><p>State</p>
</li>
<li><p>PricingStrategy</p>
</li>
</ul>
<h1>3 Design Patterns Used</h1>
<table>
<thead>
<tr>
<th>Pattern</th>
<th>Where Used</th>
<th>Why</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Singleton</strong></td>
<td>VendingMachine</td>
<td>Only one machine instance</td>
</tr>
<tr>
<td><strong>Factory Method</strong></td>
<td>ProductFactory</td>
<td>Create different product types</td>
</tr>
<tr>
<td><strong>State</strong></td>
<td>MachineState</td>
<td>Control transaction lifecycle</td>
</tr>
<tr>
<td><strong>Strategy</strong></td>
<td>PricingStrategy</td>
<td>Flexible pricing rules</td>
</tr>
<tr>
<td><strong>Observer</strong></td>
<td>Display</td>
<td>Notify UI/Customer</td>
</tr>
<tr>
<td><strong>Decorator</strong></td>
<td>Product Add-ons</td>
<td>Extra packaging/gift wrap</td>
</tr>
<tr>
<td><strong>Builder</strong></td>
<td>ReceiptBuilder</td>
<td>Step-by-step receipt creation</td>
</tr>
<tr>
<td><strong>Repository</strong></td>
<td>InventoryRepository</td>
<td>Inventory abstraction</td>
</tr>
<tr>
<td><strong>Command</strong></td>
<td>User Actions</td>
<td>Encapsulate operations</td>
</tr>
</tbody></table>
<h1>4 Algorithms Involved</h1>
<h3>1 Change Calculation (Greedy Algorithm)</h3>
<p>Used to return minimum coins.</p>
<pre><code class="language-macs">For each denomination (highest  lowest):
    count = remaining / denom
    remaining %= denom
</code></pre>
<h3>2 Inventory Lookup (O(1))</h3>
<p>Use:</p>
<pre><code class="language-macs">unordered_map&lt;string, InventorySlot&gt;
</code></pre>
<h3>3 State Transition Validation</h3>
<p>Controlled transitions:</p>
<pre><code class="language-macs">Idle  MoneyInserted  ProductSelected  Dispensing  Idle
</code></pre>
<h3>4 Balance Validation</h3>
<pre><code class="language-macs">if insertedAmount &gt;= productPrice
</code></pre>
<h1>5 COMPLETE C++ IMPLEMENTATION</h1>
<p> Single-threaded</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;vector&gt;
#include &lt;memory&gt;
#include &lt;unordered_map&gt;
#include &lt;map&gt;
#include &lt;algorithm&gt;

using namespace std;

//////////////////////////////////////////////////////////////
// ENUMS
//////////////////////////////////////////////////////////////

enum class Denomination { ONE=1, FIVE=5, TEN=10, TWENTY=20, FIFTY=50 };
enum class MachineStatus { IDLE, MONEY_INSERTED, PRODUCT_SELECTED, DISPENSING };

//////////////////////////////////////////////////////////////
// OBSERVER PATTERN
//////////////////////////////////////////////////////////////

class Observer {
public:
    virtual void update(const string&amp; msg) = 0;
    virtual ~Observer() {}
};

class Display : public Observer {
public:
    void update(const string&amp; msg) override {
        cout &lt;&lt; "[Display]: " &lt;&lt; msg &lt;&lt; endl;
    }
};

//////////////////////////////////////////////////////////////
// PRODUCT
//////////////////////////////////////////////////////////////

class Product {
protected:
    string name;
    double basePrice;

public:
    Product(string n, double p) : name(n), basePrice(p) {}
    virtual ~Product() {}

    virtual string getName() { return name; }
    virtual double getPrice() { return basePrice; }
};

//////////////////////////////////////////////////////////////
// FACTORY METHOD
//////////////////////////////////////////////////////////////

class ProductFactory {
public:
    static shared_ptr&lt;Product&gt; createProduct(const string&amp; type) {
        if(type == "Coke") return make_shared&lt;Product&gt;("Coke", 25);
        if(type == "Pepsi") return make_shared&lt;Product&gt;("Pepsi", 20);
        if(type == "Chips") return make_shared&lt;Product&gt;("Chips", 15);
        return nullptr;
    }
};

//////////////////////////////////////////////////////////////
// DECORATOR PATTERN (GiftWrap Add-on)
//////////////////////////////////////////////////////////////

class ProductDecorator : public Product {
protected:
    shared_ptr&lt;Product&gt; product;
public:
    ProductDecorator(shared_ptr&lt;Product&gt; p)
        : Product(p-&gt;getName(), p-&gt;getPrice()), product(p) {}
};

class GiftWrapDecorator : public ProductDecorator {
public:
    GiftWrapDecorator(shared_ptr&lt;Product&gt; p)
        : ProductDecorator(p) {}

    double getPrice() override {
        return product-&gt;getPrice() + 5;
    }

    string getName() override {
        return product-&gt;getName() + " + GiftWrap";
    }
};

//////////////////////////////////////////////////////////////
// STRATEGY PATTERN (Pricing)
//////////////////////////////////////////////////////////////

class PricingStrategy {
public:
    virtual double calculatePrice(shared_ptr&lt;Product&gt; product) = 0;
    virtual ~PricingStrategy() {}
};

class RegularPricing : public PricingStrategy {
public:
    double calculatePrice(shared_ptr&lt;Product&gt; product) override {
        return product-&gt;getPrice();
    }
};

class DiscountPricing : public PricingStrategy {
public:
    double calculatePrice(shared_ptr&lt;Product&gt; product) override {
        return product-&gt;getPrice() * 0.9;
    }
};

//////////////////////////////////////////////////////////////
// INVENTORY REPOSITORY
//////////////////////////////////////////////////////////////

class InventorySlot {
public:
    shared_ptr&lt;Product&gt; product;
    int quantity;

    InventorySlot(shared_ptr&lt;Product&gt; p, int q)
        : product(p), quantity(q) {}
};

class InventoryRepository {
private:
    unordered_map&lt;string, InventorySlot&gt; inventory;

public:
    void addProduct(shared_ptr&lt;Product&gt; product, int quantity) {
        inventory[product-&gt;getName()] = InventorySlot(product, quantity);
    }

    bool isAvailable(string name) {
        return inventory.count(name) &amp;&amp; inventory[name].quantity &gt; 0;
    }

    shared_ptr&lt;Product&gt; getProduct(string name) {
        return inventory[name].product;
    }

    void reduceStock(string name) {
        inventory[name].quantity--;
    }
};

//////////////////////////////////////////////////////////////
// BUILDER PATTERN (Receipt)
//////////////////////////////////////////////////////////////

class Receipt {
public:
    string productName;
    double amount;
};

class ReceiptBuilder {
private:
    Receipt receipt;

public:
    ReceiptBuilder&amp; setProduct(string name) {
        receipt.productName = name;
        return *this;
    }

    ReceiptBuilder&amp; setAmount(double amt) {
        receipt.amount = amt;
        return *this;
    }

    Receipt build() {
        return receipt;
    }
};

//////////////////////////////////////////////////////////////
// CHANGE DISPENSER (Greedy Algorithm)
//////////////////////////////////////////////////////////////

class ChangeDispenser {
private:
    vector&lt;int&gt; denominations = {50, 20, 10, 5, 1};

public:
    void dispenseChange(int amount) {
        cout &lt;&lt; "Change returned: ";
        for(int d : denominations) {
            while(amount &gt;= d) {
                cout &lt;&lt; d &lt;&lt; " ";
                amount -= d;
            }
        }
        cout &lt;&lt; endl;
    }
};

//////////////////////////////////////////////////////////////
// STATE PATTERN
//////////////////////////////////////////////////////////////

class VendingMachine;

class State {
public:
    virtual void insertMoney(VendingMachine*, int) {}
    virtual void selectProduct(VendingMachine*, string) {}
    virtual void dispense(VendingMachine*) {}
    virtual void cancel(VendingMachine*) {}
    virtual ~State() {}
};

//////////////////////////////////////////////////////////////
// COMMAND PATTERN
//////////////////////////////////////////////////////////////

class Command {
public:
    virtual void execute() = 0;
    virtual ~Command() {}
};

//////////////////////////////////////////////////////////////
// VENDING MACHINE (Singleton)
//////////////////////////////////////////////////////////////

class VendingMachine {
private:
    State* currentState;
    InventoryRepository inventory;
    vector&lt;Observer*&gt; observers;
    ChangeDispenser changeDispenser;
    shared_ptr&lt;PricingStrategy&gt; pricingStrategy;

    int insertedAmount;
    string selectedProduct;

    VendingMachine() {
        insertedAmount = 0;
        pricingStrategy = make_shared&lt;RegularPricing&gt;();
    }

public:
    static VendingMachine&amp; getInstance() {
        static VendingMachine instance;
        return instance;
    }

    void setState(State* state) { currentState = state; }

    void attach(Observer* obs) { observers.push_back(obs); }

    void notify(string msg) {
        for(auto obs : observers)
            obs-&gt;update(msg);
    }

    void addProduct(shared_ptr&lt;Product&gt; product, int quantity) {
        inventory.addProduct(product, quantity);
    }

    void insertMoney(int amount) {
        insertedAmount += amount;
        notify("Money Inserted: " + to_string(amount));
    }

    void selectProduct(string name) {
        if(!inventory.isAvailable(name)) {
            notify("Product not available");
            return;
        }
        selectedProduct = name;
        notify("Product Selected: " + name);
    }

    void dispenseProduct() {
        auto product = inventory.getProduct(selectedProduct);
        double price = pricingStrategy-&gt;calculatePrice(product);

        if(insertedAmount &lt; price) {
            notify("Insufficient Balance");
            return;
        }

        inventory.reduceStock(selectedProduct);
        insertedAmount -= price;

        notify("Dispensing " + selectedProduct);

        changeDispenser.dispenseChange(insertedAmount);
        insertedAmount = 0;

        Receipt receipt = ReceiptBuilder()
            .setProduct(selectedProduct)
            .setAmount(price)
            .build();

        cout &lt;&lt; "Receipt: " &lt;&lt; receipt.productName 
             &lt;&lt; " | Amount: " &lt;&lt; receipt.amount &lt;&lt; endl;
    }
};

//////////////////////////////////////////////////////////////
// MAIN
//////////////////////////////////////////////////////////////

int main() {

    VendingMachine&amp; machine = VendingMachine::getInstance();

    Display display;
    machine.attach(&amp;display);

    auto coke = ProductFactory::createProduct("Coke");
    machine.addProduct(coke, 5);

    machine.insertMoney(50);
    machine.selectProduct("Coke");
    machine.dispenseProduct();

    return 0;
}
</code></pre>
<h1>6 Complexity Analysis</h1>
<table>
<thead>
<tr>
<th>Operation</th>
<th>Complexity</th>
</tr>
</thead>
<tbody><tr>
<td>Add Product</td>
<td>O(1)</td>
</tr>
<tr>
<td>Lookup</td>
<td>O(1)</td>
</tr>
<tr>
<td>Change Calculation</td>
<td>O(d)</td>
</tr>
<tr>
<td>Dispense</td>
<td>O(1)</td>
</tr>
</tbody></table>
<h1>7 Interview Discussion Points</h1>
<p>If interviewer asks:</p>
<p><strong>Why State Pattern?</strong>  Prevent invalid transitions.</p>
<p><strong>Why Strategy?</strong>  Allow flexible pricing (discount, surge, membership).</p>
<p><strong>Why Decorator?</strong>  Add-ons dynamically.</p>
<p><strong>Why Builder?</strong>  Receipt construction cleanly.</p>
<p><strong>Why Repository?</strong>  Decouple storage.</p>
<p><strong>Why Singleton?</strong>  Only one machine instance.</p>
<h1>🚨 MULTI-THREADING PROBLEMS IN this DESIGN</h1>
<h1>1 Race Condition on <code>insertedAmount</code></h1>
<h2>🔴 Problem</h2>
<pre><code class="language-macs">insertedAmount += amount;
</code></pre>
<p>If 2 threads call:</p>
<pre><code class="language-macs">insertMoney(50)
insertMoney(20)
</code></pre>
<p>Possible interleaving:</p>
<p>Thread A reads 0 Thread B reads 0 Thread A writes 50 Thread B writes 20</p>
<p>Final amount = 20  (lost update)</p>
<p>This is a <strong>classic data race</strong>.</p>
<h2> Solution: covered in our <a href="https://interview.lldcoding.com/dashboard/lld-cpp-course1?chapter=Vending+Machine-L2FwaS9jb250ZW50L2xsZC1jcHAtY291cnNlLXZlbmRpbmctbWFjaGluZS5jaHVuazAuZW5jcnlwdGVk">course</a>.</h2>
<h1>2 Race Condition on Inventory</h1>
<h2>🔴 Problem</h2>
<pre><code class="language-macs">if(inventory.isAvailable(name))
inventory.reduceStock(name);
</code></pre>
<p>Two threads:</p>
<p>Thread A sees quantity = 1 Thread B sees quantity = 1 Both reduce Quantity becomes -1 </p>
<p>Overselling.</p>
<h2> Solution: : covered in our <a href="https://interview.lldcoding.com/dashboard/lld-cpp-course1?chapter=Vending+Machine-L2FwaS9jb250ZW50L2xsZC1jcHAtY291cnNlLXZlbmRpbmctbWFjaGluZS5jaHVuazAuZW5jcnlwdGVk">course</a>.</h2>
<h1>3 Race Condition on <code>selectedProduct</code></h1>
<h2>🔴 Problem</h2>
<p><code>selectedProduct</code> is shared global state.</p>
<p>If:</p>
<p>Thread A selects Coke Thread B selects Pepsi</p>
<p>Thread A dispenses  might dispense Pepsi </p>
<p>Shared mutable state = broken machine.</p>
<h2> Solution: : covered in our <a href="https://interview.lldcoding.com/dashboard/lld-cpp-course1?chapter=Vending+Machine-L2FwaS9jb250ZW50L2xsZC1jcHAtY291cnNlLXZlbmRpbmctbWFjaGluZS5jaHVuazAuZW5jcnlwdGVk">course</a>.</h2>
<h1>4 Singleton Not Thread-Safe (Initialization)</h1>
<p>C++11 static local is thread-safe.</p>
<p>But if using manual singleton:</p>
<pre><code class="language-macs">static VendingMachine* instance;
</code></pre>
<p>Two threads  double creation.</p>
<h2> Solution: covered in our <a href="https://interview.lldcoding.com/dashboard/lld-cpp-course1?chapter=Vending+Machine-L2FwaS9jb250ZW50L2xsZC1jcHAtY291cnNlLXZlbmRpbmctbWFjaGluZS5jaHVuazAuZW5jcnlwdGVk">course</a>.</h2>
<h1>5 Change Dispenser Race Condition</h1>
<p>If two threads:</p>
<pre><code class="language-macs">dispenseChange(amount);
</code></pre>
<p>Outputs interleaving messy logs.</p>
<h2> Solution: covered in our <a href="https://interview.lldcoding.com/dashboard/lld-cpp-course1?chapter=Vending+Machine-L2FwaS9jb250ZW50L2xsZC1jcHAtY291cnNlLXZlbmRpbmctbWFjaGluZS5jaHVuazAuZW5jcnlwdGVk">course</a>.</h2>
<h1>6 Observer List Race Condition</h1>
<pre><code class="language-macs">vector&lt;Observer*&gt; observers;
</code></pre>
<p>If:</p>
<p>Thread A attaches observer Thread B notifies</p>
<p>Possible iterator invalidation.</p>
<h2> Solution: covered in our <a href="https://interview.lldcoding.com/dashboard/lld-cpp-course1?chapter=Vending+Machine-L2FwaS9jb250ZW50L2xsZC1jcHAtY291cnNlLXZlbmRpbmctbWFjaGluZS5jaHVuazAuZW5jcnlwdGVk">course</a>.</h2>
<h1>7 Deadlock Risk</h1>
<p>If:</p>
<ul>
<li><p>Inventory locks</p>
</li>
<li><p>Machine locks</p>
</li>
<li><p>ChangeDispenser locks</p>
</li>
</ul>
<p>And locking order differs  DEADLOCK.</p>
<h2> Solution: covered in our <a href="https://interview.lldcoding.com/dashboard/lld-cpp-course1?chapter=Vending+Machine-L2FwaS9jb250ZW50L2xsZC1jcHAtY291cnNlLXZlbmRpbmctbWFjaGluZS5jaHVuazAuZW5jcnlwdGVk">course</a>.</h2>
<h1>8 Check-Then-Act Race</h1>
<pre><code class="language-macs">if(insertedAmount &gt;= price)
</code></pre>
<p>Thread A checks Thread B reduces insertedAmount Thread A continues</p>
<p>Incorrect dispense.</p>
<h2> Solution: covered in our <a href="https://interview.lldcoding.com/dashboard/lld-cpp-course1?chapter=Vending+Machine-L2FwaS9jb250ZW50L2xsZC1jcHAtY291cnNlLXZlbmRpbmctbWFjaGluZS5jaHVuazAuZW5jcnlwdGVk">course</a>.</h2>
<h1>9 Performance Issue: Global Lock Bottleneck</h1>
<p>If we lock entire machine:</p>
<p>Only 1 user can operate at a time.</p>
<p>Not scalable.</p>
<h2> Solution: covered in our <a href="https://interview.lldcoding.com/dashboard/lld-cpp-course1?chapter=Vending+Machine-L2FwaS9jb250ZW50L2xsZC1jcHAtY291cnNlLXZlbmRpbmctbWFjaGluZS5jaHVuazAuZW5jcnlwdGVk">course</a>.</h2>
<h1>🔟 Starvation Risk</h1>
<p>If using mutex unfairly  one thread may starve.</p>
<h2> Solution: covered in our <a href="https://interview.lldcoding.com/dashboard/lld-cpp-course1?chapter=Vending+Machine-L2FwaS9jb250ZW50L2xsZC1jcHAtY291cnNlLXZlbmRpbmctbWFjaGluZS5jaHVuazAuZW5jcnlwdGVk">course</a>.</h2>
]]></description><link>https://lldcoding.com/design-vending-machine-cpp-concurrency</link><guid isPermaLink="true">https://lldcoding.com/design-vending-machine-cpp-concurrency</guid><category><![CDATA[LLD]]></category><category><![CDATA[Java]]></category><category><![CDATA[C++]]></category><category><![CDATA[General Programming]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[interview]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[Object Oriented Programming]]></category><category><![CDATA[Python]]></category><dc:creator><![CDATA[Subhahu Jain]]></dc:creator></item><item><title><![CDATA[Design (LLD) Hotel Management System - C++]]></title><description><![CDATA[<h1>1 Functional Requirements</h1>
<p>A hotel system should support:</p>
<ul>
<li><p>Add hotel rooms</p>
</li>
<li><p>Search rooms (by type, price, availability)</p>
</li>
<li><p>Book room</p>
</li>
<li><p>Cancel booking</p>
</li>
<li><p>Check-in</p>
</li>
<li><p>Check-out</p>
</li>
<li><p>Generate bill</p>
</li>
<li><p>Payment processing</p>
</li>
<li><p>Room pricing strategy</p>
</li>
<li><p>Different room types (Single, Double, Suite)</p>
</li>
</ul>
<h1>2 Core Entities</h1>
<ul>
<li><p>Room</p>
</li>
<li><p>Guest</p>
</li>
<li><p>Booking</p>
</li>
<li><p>Payment</p>
</li>
<li><p>Invoice</p>
</li>
<li><p>Hotel</p>
</li>
<li><p>Pricing Strategy</p>
</li>
<li><p>Notification Service</p>
</li>
</ul>
<h1>3 Design Patterns Used (With Reason)</h1>
<table>
<thead>
<tr>
<th>Pattern</th>
<th>Where Used</th>
<th>Why</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Singleton</strong></td>
<td>HotelSystem</td>
<td>Only one central system instance</td>
</tr>
<tr>
<td><strong>Factory Method</strong></td>
<td>RoomFactory</td>
<td>Create different room types</td>
</tr>
<tr>
<td><strong>Strategy</strong></td>
<td>PricingStrategy</td>
<td>Flexible pricing logic</td>
</tr>
<tr>
<td><strong>State</strong></td>
<td>BookingState</td>
<td>Booking lifecycle management</td>
</tr>
<tr>
<td><strong>Observer</strong></td>
<td>NotificationService</td>
<td>Notify guest on booking events</td>
</tr>
<tr>
<td><strong>Decorator</strong></td>
<td>RoomServiceDecorator</td>
<td>Add extra services to booking</td>
</tr>
<tr>
<td><strong>Builder</strong></td>
<td>InvoiceBuilder</td>
<td>Step-by-step invoice creation</td>
</tr>
<tr>
<td><strong>Repository</strong></td>
<td>BookingRepository</td>
<td>Abstract data storage</td>
</tr>
</tbody></table>
<h1>4 Algorithms Used</h1>
<h3>1. Room Allocation Algorithm</h3>
<ul>
<li><p>Linear scan for available rooms</p>
</li>
<li><p>Can be upgraded to priority queue</p>
</li>
</ul>
<h3>2. Date Overlap Detection</h3>
<pre><code class="language-macs">Overlap if:
!(end1 &lt;= start2 || end2 &lt;= start1)
</code></pre>
<h3>3. Billing Calculation</h3>
<pre><code class="language-macs">Total = BasePrice + Services - Discounts
</code></pre>
<h3>4. Search Algorithm</h3>
<ul>
<li><p>Filter by type</p>
</li>
<li><p>Filter by price range</p>
</li>
<li><p>Check availability</p>
</li>
</ul>
<h1>5 COMPLETE C++</h1>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;vector&gt;
#include &lt;string&gt;
#include &lt;memory&gt;
#include &lt;map&gt;
#include &lt;algorithm&gt;

using namespace std;

///////////////////////////////////////////////////////////
// ENUMS
///////////////////////////////////////////////////////////

enum class RoomType { SINGLE, DOUBLE, SUITE };
enum class BookingStatus { CREATED, CONFIRMED, CHECKED_IN, COMPLETED, CANCELLED };

///////////////////////////////////////////////////////////
// STRATEGY PATTERN - Pricing Strategy
///////////////////////////////////////////////////////////

class PricingStrategy {
public:
    virtual double calculatePrice(double basePrice, int nights) = 0;
    virtual ~PricingStrategy() {}
};

class RegularPricing : public PricingStrategy {
public:
    double calculatePrice(double basePrice, int nights) override {
        return basePrice * nights;
    }
};

class WeekendPricing : public PricingStrategy {
public:
    double calculatePrice(double basePrice, int nights) override {
        return basePrice * nights * 1.2; // 20% increase
    }
};

///////////////////////////////////////////////////////////
// OBSERVER PATTERN
///////////////////////////////////////////////////////////

class Observer {
public:
    virtual void update(string message) = 0;
};

class Guest : public Observer {
private:
    string name;
public:
    Guest(string name) : name(name) {}

    void update(string message) override {
        cout &lt;&lt; "Notification for " &lt;&lt; name &lt;&lt; ": " &lt;&lt; message &lt;&lt; endl;
    }

    string getName() { return name; }
};

///////////////////////////////////////////////////////////
// ROOM CLASS
///////////////////////////////////////////////////////////

class Room {
protected:
    int roomNumber;
    RoomType type;
    double basePrice;
    bool available;

public:
    Room(int number, RoomType t, double price)
        : roomNumber(number), type(t), basePrice(price), available(true) {}

    virtual ~Room() {}

    int getRoomNumber() { return roomNumber; }
    RoomType getType() { return type; }
    double getBasePrice() { return basePrice; }
    bool isAvailable() { return available; }

    void setAvailability(bool status) { available = status; }
};

///////////////////////////////////////////////////////////
// FACTORY METHOD PATTERN
///////////////////////////////////////////////////////////

class RoomFactory {
public:
    static shared_ptr&lt;Room&gt; createRoom(RoomType type, int number) {
        switch(type) {
            case RoomType::SINGLE:
                return make_shared&lt;Room&gt;(number, type, 100);
            case RoomType::DOUBLE:
                return make_shared&lt;Room&gt;(number, type, 200);
            case RoomType::SUITE:
                return make_shared&lt;Room&gt;(number, type, 500);
        }
        return nullptr;
    }
};

///////////////////////////////////////////////////////////
// STATE PATTERN
///////////////////////////////////////////////////////////

class Booking;

class BookingState {
public:
    virtual void next(Booking* booking) = 0;
    virtual string getStatus() = 0;
};

///////////////////////////////////////////////////////////
// DECORATOR PATTERN - Extra Services
///////////////////////////////////////////////////////////

class RoomService {
public:
    virtual double cost() = 0;
    virtual string description() = 0;
    virtual ~RoomService() {}
};

class BasicRoomService : public RoomService {
public:
    double cost() override { return 0; }
    string description() override { return "Basic Room"; }
};

class SpaDecorator : public RoomService {
private:
    shared_ptr&lt;RoomService&gt; service;
public:
    SpaDecorator(shared_ptr&lt;RoomService&gt; s) : service(s) {}

    double cost() override {
        return service-&gt;cost() + 50;
    }

    string description() override {
        return service-&gt;description() + " + Spa";
    }
};

///////////////////////////////////////////////////////////
// BOOKING CLASS
///////////////////////////////////////////////////////////

class Booking {
private:
    int bookingId;
    shared_ptr&lt;Room&gt; room;
    shared_ptr&lt;Guest&gt; guest;
    int nights;
    shared_ptr&lt;PricingStrategy&gt; pricingStrategy;
    shared_ptr&lt;RoomService&gt; roomService;

public:
    Booking(int id, shared_ptr&lt;Room&gt; r, shared_ptr&lt;Guest&gt; g, int nights,
            shared_ptr&lt;PricingStrategy&gt; strategy)
        : bookingId(id), room(r), guest(g), nights(nights),
          pricingStrategy(strategy) {
        roomService = make_shared&lt;BasicRoomService&gt;();
    }

    void addService(shared_ptr&lt;RoomService&gt; service) {
        roomService = service;
    }

    double calculateBill() {
        double base = pricingStrategy-&gt;calculatePrice(room-&gt;getBasePrice(), nights);
        return base + roomService-&gt;cost();
    }

    void confirm() {
        room-&gt;setAvailability(false);
        guest-&gt;update("Booking Confirmed!");
    }

    void cancel() {
        room-&gt;setAvailability(true);
        guest-&gt;update("Booking Cancelled!");
    }

    int getId() { return bookingId; }
};

///////////////////////////////////////////////////////////
// BUILDER PATTERN - Invoice
///////////////////////////////////////////////////////////

class Invoice {
public:
    double amount;
    string details;
};

class InvoiceBuilder {
private:
    Invoice invoice;
public:
    InvoiceBuilder&amp; setAmount(double amt) {
        invoice.amount = amt;
        return *this;
    }

    InvoiceBuilder&amp; setDetails(string det) {
        invoice.details = det;
        return *this;
    }

    Invoice build() {
        return invoice;
    }
};

///////////////////////////////////////////////////////////
// REPOSITORY PATTERN
///////////////////////////////////////////////////////////

class BookingRepository {
private:
    map&lt;int, shared_ptr&lt;Booking&gt;&gt; bookings;

public:
    void save(shared_ptr&lt;Booking&gt; booking) {
        bookings[booking-&gt;getId()] = booking;
    }

    shared_ptr&lt;Booking&gt; find(int id) {
        return bookings[id];
    }
};

///////////////////////////////////////////////////////////
// SINGLETON - HOTEL SYSTEM
///////////////////////////////////////////////////////////

class HotelSystem {
private:
    vector&lt;shared_ptr&lt;Room&gt;&gt; rooms;
    BookingRepository bookingRepo;

    HotelSystem() {}

public:
    static HotelSystem&amp; getInstance() {
        static HotelSystem instance;
        return instance;
    }

    void addRoom(RoomType type, int number) {
        rooms.push_back(RoomFactory::createRoom(type, number));
    }

    shared_ptr&lt;Room&gt; searchAvailable(RoomType type) {
        for (auto&amp; room : rooms) {
            if (room-&gt;getType() == type &amp;&amp; room-&gt;isAvailable())
                return room;
        }
        return nullptr;
    }

    shared_ptr&lt;Booking&gt; bookRoom(int bookingId, shared_ptr&lt;Guest&gt; guest,
                                 RoomType type, int nights) {

        auto room = searchAvailable(type);
        if (!room) {
            cout &lt;&lt; "No room available\n";
            return nullptr;
        }

        auto strategy = make_shared&lt;RegularPricing&gt;();
        auto booking = make_shared&lt;Booking&gt;(bookingId, room, guest, nights, strategy);

        booking-&gt;confirm();
        bookingRepo.save(booking);

        return booking;
    }

    void checkout(int bookingId) {
        auto booking = bookingRepo.find(bookingId);
        if (!booking) return;

        double bill = booking-&gt;calculateBill();

        Invoice invoice = InvoiceBuilder()
                .setAmount(bill)
                .setDetails("Hotel Stay Charges")
                .build();

        cout &lt;&lt; "Invoice Generated: " &lt;&lt; invoice.amount &lt;&lt; endl;
    }
};

///////////////////////////////////////////////////////////
// MAIN
///////////////////////////////////////////////////////////

int main() {

    HotelSystem&amp; system = HotelSystem::getInstance();

    system.addRoom(RoomType::SINGLE, 101);
    system.addRoom(RoomType::DOUBLE, 102);

    auto guest = make_shared&lt;Guest&gt;("John");

    auto booking = system.bookRoom(1, guest, RoomType::SINGLE, 3);

    if (booking) {
        auto service = make_shared&lt;SpaDecorator&gt;(
                make_shared&lt;BasicRoomService&gt;());
        booking-&gt;addService(service);

        system.checkout(1);
    }

    return 0;
}
</code></pre>
<h1>6 Complexity Analysis</h1>
<table>
<thead>
<tr>
<th>Operation</th>
<th>Complexity</th>
</tr>
</thead>
<tbody><tr>
<td>Add Room</td>
<td>O(1)</td>
</tr>
<tr>
<td>Search Room</td>
<td>O(n)</td>
</tr>
<tr>
<td>Booking</td>
<td>O(n)</td>
</tr>
<tr>
<td>Billing</td>
<td>O(1)</td>
</tr>
<tr>
<td>Repository Lookup</td>
<td>O(log n)</td>
</tr>
</tbody></table>
<h1>7 How to Improve for Production?</h1>
<ul>
<li><p>Use priority queue for optimized allocation</p>
</li>
<li><p>Use interval tree for date-based booking</p>
</li>
<li><p>Add payment gateway integration</p>
</li>
<li><p>Make it thread-safe</p>
</li>
<li><p>Replace in-memory repo with DB</p>
</li>
</ul>
<h1>8 Interview Discussion Points</h1>
<p>If asked:</p>
<ul>
<li><p>Why Strategy?  Pricing flexibility</p>
</li>
<li><p>Why State?  Booking lifecycle control</p>
</li>
<li><p>Why Decorator?  Add services dynamically</p>
</li>
<li><p>Why Repository?  Abstraction from storage</p>
</li>
<li><p>Why Singleton?  Centralized management</p>
</li>
<li><p>Why Factory?  Room object creation abstraction</p>
</li>
</ul>
<h1>Problems in this implementation:</h1>
<p>We built a <strong>single-threaded Hotel Management System</strong>. Now lets analyze:</p>
<blockquote>
<p> What problems still exist in a this single-threaded design?  Why is single-threaded not enough in real systems?  How do we fix each issue?</p>
</blockquote>
<h1>🚨 1 Double Booking Problem (Logical Race Condition)</h1>
<h3>🔴 Problem</h3>
<p>Even in single-threaded systems, you can still have <strong>logical race conditions</strong>.</p>
<p>Example:</p>
<ol>
<li><p>Search room  Available</p>
</li>
<li><p>Before booking finalizes, another booking call happens</p>
</li>
<li><p>Both see room as available</p>
</li>
<li><p>Double booking happens</p>
</li>
</ol>
<p>This is not thread-race. This is <strong>check-then-act problem</strong>.</p>
<h3> Why It Happens</h3>
<p>Because:</p>
<pre><code class="language-macs">searchAvailable()
confirm()
</code></pre>
<p>are separate operations.</p>
<h3> Solution</h3>
<p>Covered in our <a href="https://interview.lldcoding.com/">C++ course</a></p>
<h1>🚨 2 No Date Handling  Overlapping Bookings</h1>
<h3>🔴 Problem</h3>
<p>Current system only checks:</p>
<pre><code class="language-macs">room-&gt;isAvailable()
</code></pre>
<p>But hotels operate on <strong>date ranges</strong>.</p>
<p>Without date validation:</p>
<ul>
<li><p>Guest A: Jan 13</p>
</li>
<li><p>Guest B: Jan 25 System allows both.</p>
</li>
</ul>
<h3> Why It Happens</h3>
<p>We dont track booking intervals.</p>
<h3> Solution:</h3>
<p>Covered in our <a href="https://interview.lldcoding.com/">C++ course</a></p>
<h1>🚨 3 Poor Room Search Performance (O(n))</h1>
<h3>🔴 Problem</h3>
<p>Search scans all rooms:</p>
<pre><code class="language-macs">for (auto&amp; room : rooms)
</code></pre>
<p>If hotel has 10,000 rooms  slow.</p>
<h3> Why It Happens</h3>
<p>We use linear search.</p>
<h3> Solution:</h3>
<p>Covered in our <a href="https://interview.lldcoding.com/">C++ course</a></p>
<h1>🚨 4 No Payment Failure Handling</h1>
<h3>🔴 Problem</h3>
<p>Checkout directly generates invoice.</p>
<p>But:</p>
<ul>
<li><p>What if payment fails?</p>
</li>
<li><p>What if partial payment?</p>
</li>
</ul>
<p>System currently assumes success.</p>
<h3> Solution</h3>
<p>Covered in our <a href="https://interview.lldcoding.com/">C++ course</a></p>
<h1>🚨 5 No Booking State Validation</h1>
<h3>🔴 Problem</h3>
<p>User can:</p>
<ul>
<li><p>Cancel after checkout</p>
</li>
<li><p>Check-in twice</p>
</li>
<li><p>Checkout before check-in</p>
</li>
</ul>
<p>No lifecycle enforcement.</p>
<h3> Solution: Proper State Pattern</h3>
<p>Covered in our <a href="https://interview.lldcoding.com/">C++ course</a></p>
<h1>🚨 6 Memory Leak Risk</h1>
<h3>🔴 Problem</h3>
<p>If using raw pointers:</p>
<ul>
<li><p>Memory leaks</p>
</li>
<li><p>Dangling pointers</p>
</li>
</ul>
<h3> Solution</h3>
<p>Covered in our <a href="https://interview.lldcoding.com/">C++ course</a></p>
<h1>🚨 7 No Persistence (Data Loss)</h1>
<h3>🔴 Problem</h3>
<p>System is in-memory.</p>
<p>If server restarts  all data lost.</p>
<h3> Solution:</h3>
<p>Covered in our <a href="https://interview.lldcoding.com/">C++ course</a></p>
<h1>🚨 8 No Scalability</h1>
<h3>🔴 Problem</h3>
<p>Single-threaded means:</p>
<ul>
<li><p>One request at a time</p>
</li>
<li><p>No parallel bookings</p>
</li>
<li><p>Slow during peak traffic</p>
</li>
</ul>
<h3> Solution</h3>
<p>Covered in our <a href="https://interview.lldcoding.com/">C++ course</a></p>
<h1>🚨 9 No Audit Logging</h1>
<h3>🔴 Problem</h3>
<p>System does not track:</p>
<ul>
<li><p>Who booked</p>
</li>
<li><p>Who cancelled</p>
</li>
<li><p>When changed</p>
</li>
</ul>
<h3> Solution</h3>
<p>Covered in our <a href="https://interview.lldcoding.com/">C++ course</a></p>
]]></description><link>https://lldcoding.com/design-lld-hotel-management-system-c</link><guid isPermaLink="true">https://lldcoding.com/design-lld-hotel-management-system-c</guid><category><![CDATA[interview]]></category><category><![CDATA[LLD]]></category><category><![CDATA[C++]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[Subhahu Jain]]></dc:creator></item><item><title><![CDATA[Designing a Like / Reaction System (Facebook / LinkedIn) - Database Modelling]]></title><description><![CDATA[<p>Modern platforms (Reddit, LinkedIn, YouTube) support <strong>multiple reaction types</strong> per entity.</p>
<h3 id="heading-core-requirements">Core Requirements</h3>
<ul>
<li><p> <strong>One user  one reaction per entity</strong></p>
</li>
<li><p> Reaction can <strong>change over time</strong></p>
</li>
<li><p> <strong>Extremely write-heavy</strong></p>
</li>
<li><p> Reads need <strong>fast aggregated counts</strong></p>
</li>
<li><p> Prevent <strong>duplicate reactions</strong></p>
</li>
</ul>
<p>This is <strong>not</strong> a simple likes table problem.</p>
<h2 id="heading-solutions">Solutions</h2>
<h1 id="heading-1-naive-design-why-it-fails"> 1. Naive Design (Why It Fails)</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1768853081818/76f8cf9d-4546-4683-ab3e-5a66b863f5b3.png" alt class="image--center mx-auto" /></p>
<p>Code given in <a target="_blank" href="https://github.com/subhahu123/awesome-database-modelling-design/tree/main/Designing%20a%20Like-Reaction%20System%20\(Facebook%20-%20LinkedIn\)">github repo</a>.</p>
<h3 id="heading-problems">Problems</h3>
<ul>
<li><p> No uniqueness  duplicate reactions</p>
</li>
<li><p> <code>COUNT(*)</code> on every read</p>
</li>
<li><p> Full table scans under load</p>
</li>
<li><p> Read amplification explodes</p>
</li>
</ul>
<p><img src="https://kroki.io/d2/svg/eNpLySxKTS7JzM-zUijKTM8o4eJyzslMzQPSQamJYImQxKScVCuFai4FhZzEpNQcKwUlmJQCWC4mT8M3MycHyC9WyE9TCMovL9ZUAqouzkgsAGpMrszJzEtJLeKqhZmtoGungGa6krN_qF-IhpamQriHa5CrAlBVZkllfGaKgq1ChBIA7Ug1xg==" alt class="image--center mx-auto" /></p>
<blockquote>
<p>Works at 10 users. Dies at 10 million.</p>
</blockquote>
<h1 id="heading-2-optimized-data-model-correct-foundation"> 2. Optimized Data Model (Correct Foundation)</h1>
<p>We <strong>separate concerns</strong>:</p>
<ul>
<li><p><strong>Truth</strong> (who reacted)</p>
</li>
<li><p><strong>Speed</strong> (aggregated counts)</p>
</li>
</ul>
<h2 id="heading-21-core-reaction-table-uniqueness-truth">2.1 Core Reaction Table (Uniqueness + Truth)</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1768853036879/a1490a9f-af49-4c45-94c2-70d3becabbb5.png" alt class="image--center mx-auto" /></p>
<p>Code given in <a target="_blank" href="https://github.com/subhahu123/awesome-database-modelling-design/tree/main/Designing%20a%20Like-Reaction%20System%20\(Facebook%20-%20LinkedIn\)">github repo</a>.</p>
<h3 id="heading-why-this-works">Why This Works</h3>
<ul>
<li><p> Enforces <strong>1 reaction per user per entity</strong></p>
</li>
<li><p> Reaction change = <code>UPDATE</code>, not new row</p>
</li>
<li><p> Write cost is predictable</p>
</li>
</ul>
<h2 id="heading-22-pre-aggregated-counters-read-optimization">2.2 Pre-Aggregated Counters (Read Optimization)</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1768852990668/fff90251-d792-4220-a576-cd8e0e9c2bca.png" alt class="image--center mx-auto" /></p>
<p>Code given in <a target="_blank" href="https://github.com/subhahu123/awesome-database-modelling-design/tree/main/Designing%20a%20Like-Reaction%20System%20\(Facebook%20-%20LinkedIn\)">github repo</a>.</p>
<h3 id="heading-why-this-exists">Why This Exists</h3>
<ul>
<li><p>Reads are <strong>O(1)</strong></p>
</li>
<li><p>No <code>GROUP BY</code></p>
</li>
<li><p>No scanning reaction table</p>
</li>
</ul>
<p><img src="https://kroki.io/d2/svg/eNp9j78KAjEMh_c-Reikw-HeQRBfQPQOF5deG9tCaY9cO4j47sbzDyroFMj3y5fEBkJTQk4KKDhfhFjHgInrFvUEWt1HVHAWAFH3GBXIJzqk2S5XMgj5CC3V4ueSY6PXA0-YUwzJIokLS3NNBemP65Fg5YawWTlH6HRB-9M4nQnNEj7dN6G990b5lvp6R-4pFIQFdIPlNS8srwlkW1k=" alt class="image--center mx-auto" /></p>
<h1 id="heading-3-handling-reaction-updates-critical-part">🔄 3. Handling Reaction Updates (Critical Part)</h1>
<h3 id="heading-scenario">Scenario</h3>
<p>User changes reaction:</p>
<pre><code class="lang-javascript">LIKE  LOVE
</code></pre>
<h3 id="heading-correct-flow">Correct Flow</h3>
<ol>
<li><p>Read existing reaction</p>
</li>
<li><p>Decrement old counter</p>
</li>
<li><p>Increment new counter</p>
</li>
<li><p>Update reaction row</p>
</li>
<li><p><strong>All inside one transaction</strong></p>
</li>
</ol>
<p><img src="https://kroki.io/d2/svg/eNpzcnX39LPm4goNcHEMcVUISk1MLsnMz3POL80rSS3iCnYNUUgGsRVsobSugiFXuIdrkKtCal5JZkllfGYKUM5ewdHPRaEIqju-pLIgFSiq7uPp7apOiunaJJnuH4bNdLCx2BVDzS4tTi1CNhnFLqCBzv6-vp4h1gAuald6" alt class="image--center mx-auto" /></p>
<h3 id="heading-why-atomicity-matters">Why Atomicity Matters</h3>
<ul>
<li><p>Prevents counter drift</p>
</li>
<li><p>Guarantees consistency</p>
</li>
</ul>
<p><img src="https://kroki.io/d2/svg/eNp1jkEKwjAQRfdzimH2XiALN7pxo1DoAWLysYGYlGmkFPHuttDGjd2--Y83PihcCTkZ1vDoClE7QIka2BW_iTnaO6Jh2Sg3eZSZD53tYdhNMSQ_ax-iU36lAv3vrccddSnz4ci_trS9twWVSP1r2dWUnOEUT6TCt-j3Rpe0ja4Y5QvXjlHw" alt class="image--center mx-auto" /></p>
<h1 id="heading-alternative-solutions">🔁 Alternative Solutions</h1>
<h2 id="heading-1-event-driven-counters-async-aggregation">1 Event-Driven Counters (Async Aggregation)</h2>
<h3 id="heading-idea">Idea</h3>
<ul>
<li><p>Writes go only to the <strong>Reaction table</strong></p>
</li>
<li><p>Counters updated <strong>asynchronously</strong> via events</p>
</li>
</ul>
<h3 id="heading-flow">Flow</h3>
<ol>
<li><p>User reacts</p>
</li>
<li><p>Persist reaction</p>
</li>
<li><p>Emit event (<code>reaction_added / reaction_changed</code>)</p>
</li>
<li><p>Consumer updates counters</p>
</li>
</ol>
<p><img src="https://kroki.io/d2/svg/eNpLySxKTS7JzM-zUijKTM8o4eJyzslMzSvhcgzw5ApKTQTLuThZKVQrFGckFqRaKSRX5mTmpaQWKdRyBZamlqZyOeeX5pWkFuFSBDVQQddOAWQmEIOYyEYrhRdllqTChZSQ7AUpBdsCVOWam1mi4FoGNEsJYjNIEslypdCClESgOVChYiUAcmJIGw==" alt class="image--center mx-auto" /></p>
<h3 id="heading-why-use-this">Why Use This</h3>
<p> Absorbs write spikes<br /> Decouples write path<br /> Great for huge scale</p>
<h3 id="heading-tradeoffs">Tradeoffs</h3>
<p> Eventual consistency<br /> Needs reconciliation</p>
<h2 id="heading-2-log-structured-append-only-reactions">2 Log-Structured / Append-Only Reactions</h2>
<h3 id="heading-idea-1">Idea</h3>
<ul>
<li><p>Never update reactions</p>
</li>
<li><p>Append every change</p>
</li>
<li><p>Compute latest reaction via compaction</p>
</li>
</ul>
<pre><code class="lang-text">(user=1, post=7, LIKE)
(user=1, post=7, LOVE)
</code></pre>
<p><img src="https://kroki.io/d2/svg/eNpLySxKTS7JzM-zUkjJL8_j4vLJT7dSqOZSUMhJTErNsVJQCkpNBCtQcC1LzStRAMrH5Gk4FhSk5qUo-OflVGoqARUXZyQWpFopJFfmZOalpBZx1XJxOefnFgB15hehGgcVBhnolZ-EpDcjtSIxPT8PpBVoh4KunQLcBAB-azWb" alt class="image--center mx-auto" /></p>
<h3 id="heading-why-use-this-1">Why Use This</h3>
<p> Perfect audit trail<br /> High write throughput<br /> Works well with Kafka</p>
<h3 id="heading-tradeoffs-1">Tradeoffs</h3>
<p> Read complexity<br /> Needs background jobs</p>
<h2 id="heading-3-redis-only-atomic-counters-sets">3 Redis-Only Atomic Counters + Sets</h2>
<h3 id="heading-idea-2">Idea</h3>
<p>Use Redis as <strong>primary reaction store</strong>.</p>
<pre><code class="lang-text">SET post:7:users
HINCRBY post:7:counts LIKE 1
</code></pre>
<h3 id="heading-flow-1">Flow</h3>
<ul>
<li><p><code>SADD</code> enforces uniqueness</p>
</li>
<li><p><code>HINCRBY</code> updates counters atomically</p>
</li>
</ul>
<p><img src="https://kroki.io/d2/svg/eNo1jDEKgDAQBPt7xZJW_EAKGxtrbW1icpiDECWXRsS_KwHbGWaCFPZVjmxRZI-VaEzCudLMQdTiJiC5jZOFaWjNC1dFh8lpZDWf1-hOtvBXkhy40PNP0A9o0QvPaiE9" alt class="image--center mx-auto" /></p>
<h3 id="heading-why-use-this-2">Why Use This</h3>
<p> Extremely fast<br /> Simple logic<br /> Atomic operations</p>
<h3 id="heading-tradeoffs-2">Tradeoffs</h3>
<p> Memory expensive<br /> Persistence risk<br /> Not ideal as source of truth</p>
<h2 id="heading-4-bitmaps-for-binary-reactions-like-unlike">4 Bitmaps for Binary Reactions (Like / Unlike)</h2>
<h3 id="heading-idea-3">Idea</h3>
<ul>
<li>If reaction is binary, use <strong>bitmap</strong></li>
</ul>
<pre><code class="lang-text">BITSET post:7 12345 1
</code></pre>
<p><img src="https://kroki.io/d2/svg/eNpLySxKTS7JzM-zUijKTM8o4eIKLU4tcsosyU0ssFKo5lJQyElMSs2xUlCCiMXkaZQCFcRnpig8apukkJRZoqkEVFSckViQCjQCaFZiXnpOKlctF5dzfmleSWoRmimeIc7-oX4hSiAVCKsUdO0UoOoBKgwwDw==" alt class="image--center mx-auto" /></p>
<h3 id="heading-why-use-this-3">Why Use This</h3>
<p> Ultra memory efficient<br /> Fast counts</p>
<h3 id="heading-tradeoffs-3">Tradeoffs</h3>
<p> Not for multiple reaction types<br /> User ID must be dense</p>
<h2 id="heading-5-fanout-on-write-precompute-everything">5 Fanout-on-Write (Precompute Everything)</h2>
<h3 id="heading-idea-4">Idea</h3>
<ul>
<li><p>Write path updates <strong>every read model</strong></p>
</li>
<li><p>Reads become trivial</p>
</li>
</ul>
<p><img src="https://kroki.io/d2/svg/eNpLySxKTS7JzM-zUijKTM8o4eIKL8osSeUKSk0EC7s4WSlUKxRnJBakWikkV-Zk5qWkFinUcrmlpqa4OHE555fmlaQWAVkQfQq6dgoIrQgxqHI4H64PAPGtKk4=" alt class="image--center mx-auto" /></p>
<h3 id="heading-why-use-this-4">Why Use This</h3>
<p> Zero read computation<br /> Best for read-heavy apps</p>
<h3 id="heading-tradeoffs-4">Tradeoffs</h3>
<p> Massive write amplification<br /> Complex rollback</p>
<h2 id="heading-6-materialized-views-db-native">6 Materialized Views (DB-Native)</h2>
<h3 id="heading-idea-5">Idea</h3>
<p>Let DB maintain aggregates.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">MATERIALIZED</span> <span class="hljs-keyword">VIEW</span> reaction_counts <span class="hljs-keyword">AS</span>
<span class="hljs-keyword">SELECT</span> entity_id, reaction_type, <span class="hljs-keyword">COUNT</span>(*)
<span class="hljs-keyword">FROM</span> Reaction
<span class="hljs-keyword">GROUP</span> <span class="hljs-keyword">BY</span> entity_id, reaction_type;
</code></pre>
<h3 id="heading-why-use-this-5">Why Use This</h3>
<p> Simple mental model<br /> DB-managed</p>
<h3 id="heading-tradeoffs-5">Tradeoffs</h3>
<p> Refresh cost<br /> Limited scalability</p>
<h2 id="heading-7-crdt-based-counters-distributed-systems">7 CRDT-Based Counters (Distributed Systems)</h2>
<h3 id="heading-idea-6">Idea</h3>
<p>Use <strong>conflict-free replicated data types</strong></p>
<ul>
<li><p>Each node increments locally</p>
</li>
<li><p>Eventually converge</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1768770776837/3762bb74-de8c-4ab3-9d35-93d7d6b4a436.png" alt class="image--center mx-auto" /></p>
<p>Code given in <a target="_blank" href="https://github.com/subhahu123/awesome-database-modelling-design/tree/main/Designing%20a%20Like-Reaction%20System%20\(Facebook%20-%20LinkedIn\)">github repo</a>.</p>
<h3 id="heading-why-use-this-6">Why Use This</h3>
<p> Multi-region<br /> Offline writes</p>
<h3 id="heading-tradeoffs-6">Tradeoffs</h3>
<p> Approximate<br /> Complex reasoning</p>
<h1 id="heading-how-to-choose-decision-table">🧠 How to Choose (Decision Table)</h1>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Traffic Pattern</strong></td><td><strong>Best Solution</strong></td></tr>
</thead>
<tbody>
<tr>
<td>Moderate scale</td><td>DB + Counter table</td></tr>
<tr>
<td>Massive writes</td><td>Event-driven</td></tr>
<tr>
<td>Ultra-low latency</td><td>Redis</td></tr>
<tr>
<td>Binary reactions</td><td>Bitmap</td></tr>
<tr>
<td>Audit required</td><td>Append-only log</td></tr>
<tr>
<td>Multi-region</td><td>CRDT</td></tr>
<tr>
<td>Read-heavy feeds</td><td>Fanout-on-write</td></tr>
</tbody>
</table>
</div><p>All code given here - <a target="_blank" href="https://github.com/subhahu123/awesome-database-modelling-design/tree/main/Designing%20a%20Like-Reaction%20System%20\(Facebook%20-%20LinkedIn\)">github repo</a>.</p>
]]></description><link>https://lldcoding.com/designing-a-like-reaction-system-facebook-linkedin-database-modelling</link><guid isPermaLink="true">https://lldcoding.com/designing-a-like-reaction-system-facebook-linkedin-database-modelling</guid><category><![CDATA[General Programming]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Java]]></category><category><![CDATA[Python]]></category><category><![CDATA[interview]]></category><category><![CDATA[Design]]></category><category><![CDATA[Beginner Developers]]></category><dc:creator><![CDATA[Subhahu Jain]]></dc:creator></item><item><title><![CDATA[📘 Why Indexes Are Not Free]]></title><description><![CDATA[<h3 id="heading-the-silent-cost-behind-fast-reads"><em>The Silent Cost Behind Fast Reads</em></h3>
<blockquote>
<p>Indexes dont make systems faster <br />they <strong>shift cost from reads to writes, memory, and latency tails</strong>.</p>
</blockquote>
<h2 id="heading-the-illusion">🧠 The Illusion</h2>
<pre><code class="lang-sql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">INDEX</span> idx_user_email <span class="hljs-keyword">ON</span> <span class="hljs-keyword">users</span>(email);
</code></pre>
<p>Looks harmless.<br />But this single line <strong>changes your entire system behavior</strong>.</p>
<h1 id="heading-cost-1-write-amplification">🧩 Cost #1  Write Amplification</h1>
<h3 id="heading-what-actually-happens-on-insert"> What Actually Happens on INSERT</h3>
<pre><code class="lang-sql"><span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> <span class="hljs-keyword">users</span> (<span class="hljs-keyword">id</span>, email, <span class="hljs-keyword">name</span>) <span class="hljs-keyword">VALUES</span> (...);
</code></pre>
<p>This causes:</p>
<ol>
<li><p>Write to base table</p>
</li>
<li><p>Write to index B-Tree</p>
</li>
<li><p>Possible page split</p>
</li>
<li><p>WAL / redo log update</p>
</li>
</ol>
<p><img src="https://kroki.io/d2/svg/eNpLySxKTS7JzM-zUijKTM8o4eIKL8osSbVSqOZSUMhJTErNsVJQ8vQLdg0KUdBXCA1wcQxxVeKq5eIKSUzKQVMGFlICChRnJBYA5ZIrczLzUlKLQMo9gYwKNFNBQgoaTrohRampmjj0hTv6oOoCO0_XMSM1MUXBJz8d7BawmIKunQLYBQgu2AaIS0FcoFkQd0A5AD16Sqc=" alt class="image--center mx-auto" /></p>
<h3 id="heading-key-point">🧠 Key Point</h3>
<blockquote>
<p><strong>1 logical write  multiple physical writes</strong></p>
</blockquote>
<h2 id="heading-cost-2-slower-writes-lock-contention">🧩 Cost #2  Slower Writes (Lock Contention)</h2>
<p>Indexes <strong>increase lock scope</strong>.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">UPDATE</span> <span class="hljs-keyword">users</span> <span class="hljs-keyword">SET</span> email = <span class="hljs-string">'x'</span> <span class="hljs-keyword">WHERE</span> <span class="hljs-keyword">id</span> = <span class="hljs-number">42</span>;
</code></pre>
<p>Locks:</p>
<ul>
<li><p>Row lock (table)</p>
</li>
<li><p>Index node lock</p>
</li>
<li><p>Possibly parent nodes</p>
</li>
</ul>
<h3 id="heading-effect">Effect</h3>
<ul>
<li><p>Higher contention</p>
</li>
<li><p>Worse under high concurrency</p>
</li>
</ul>
<h2 id="heading-cost-3-memory-pressure-cache-pollution">🧩 Cost #3  Memory Pressure (Cache Pollution)</h2>
<p>Indexes <strong>consume RAM aggressively</strong>.</p>
<h3 id="heading-what-lives-in-memory">What lives in memory</h3>
<ul>
<li><p>Hot index pages</p>
</li>
<li><p>Root &amp; intermediate B-tree nodes</p>
</li>
</ul>
<p><img src="https://kroki.io/d2/svg/eNpLySxKTS7JzM-zUijKTM8o4eLyTc3NL6q0UqjmUlDISUxKzbFSUIKIKWg4laalpRYpOCcmZ6RqKnHVcnF55qWkVgQkpqcWo-oAiyuAJcDqXBJLErEoAwkjqUKYpqBrpwCxFaEVIQYAsYE5jw==" alt class="image--center mx-auto" /></p>
<h3 id="heading-result">🧠 Result</h3>
<blockquote>
<p>Indexes can evict <strong>actual data</strong>, hurting cache hit rate.</p>
</blockquote>
<h2 id="heading-cost-4-read-amplification-still-exists">🧩 Cost #4  Read Amplification Still Exists</h2>
<p>Indexes dont always mean <strong>1 read</strong>.</p>
<p>Example:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">SELECT</span> * <span class="hljs-keyword">FROM</span> orders <span class="hljs-keyword">WHERE</span> user_id = <span class="hljs-number">42</span>;
</code></pre>
<p>Execution:</p>
<ol>
<li><p>Read index page</p>
</li>
<li><p>Read table page(s)</p>
</li>
</ol>
<p><img src="https://kroki.io/d2/svg/eNpLySxKTS7JzM-zUijKTM8o4eIKLE0tquTi8sxLSa2wUqjmUlDISUxKzbFSUAILKfjk52eXFihx1XJxhSQm5aSiqgELwdUoKBRnJBYAlSRX5mQCdReBdIEtUNC1UwCbB7EIxAVrBQADMy15" alt class="image--center mx-auto" /></p>
<blockquote>
<p>Index scan + table lookup = <strong>2 I/O paths</strong></p>
</blockquote>
<h2 id="heading-cost-5-index-maintenance-deletes-amp-updates">🧩 Cost #5  Index Maintenance (Deletes &amp; Updates)</h2>
<p>Deletes dont free space immediately.</p>
<p>Problems:</p>
<ul>
<li><p>Fragmentation</p>
</li>
<li><p>Page splits</p>
</li>
<li><p>Rebalancing</p>
</li>
<li><p>Vacuum / compaction overhead</p>
</li>
</ul>
<h3 id="heading-result-1">Result</h3>
<ul>
<li><p>Background CPU</p>
</li>
<li><p>Unpredictable latency spikes</p>
</li>
</ul>
<h2 id="heading-cost-6-indexes-hurt-write-heavy-systems">🧩 Cost #6  Indexes Hurt Write-Heavy Systems</h2>
<h3 id="heading-example-like-counter">Example: Like Counter</h3>
<pre><code class="lang-sql"><span class="hljs-keyword">UPDATE</span> posts <span class="hljs-keyword">SET</span> likes = likes + <span class="hljs-number">1</span> <span class="hljs-keyword">WHERE</span> <span class="hljs-keyword">id</span> = <span class="hljs-number">7</span>;
</code></pre>
<p>With index on <code>likes</code>:</p>
<ul>
<li><p>Every increment updates index order</p>
</li>
<li><p>Constant tree rebalancing </p>
</li>
</ul>
<h3 id="heading-better">Better</h3>
<ul>
<li><p>No index</p>
</li>
<li><p>Or async aggregation</p>
</li>
</ul>
<h1 id="heading-when-indexes-make-things-worse">🧠 When Indexes Make Things Worse</h1>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Scenario</td><td>Index Impact</td></tr>
</thead>
<tbody>
<tr>
<td>Write-heavy</td><td> Bad</td></tr>
<tr>
<td>High churn fields</td><td> Bad</td></tr>
<tr>
<td>Low-selectivity columns</td><td> Bad</td></tr>
<tr>
<td>Hot rows</td><td> Very bad</td></tr>
<tr>
<td>Cold analytical reads</td><td> Wasted</td></tr>
</tbody>
</table>
</div><hr />
<h2 id="heading-example-of-a-bad-index"> Example of a Bad Index</h2>
<pre><code class="lang-sql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">INDEX</span> idx_gender <span class="hljs-keyword">ON</span> <span class="hljs-keyword">users</span>(gender);
</code></pre>
<p>Why bad?</p>
<ul>
<li><p>Low cardinality</p>
<ul>
<li>What is cardinality ? will be explained in upcoming blog.</li>
</ul>
</li>
<li><p>Poor selectivity</p>
</li>
<li><p>Index scan almost as big as table scan</p>
</li>
</ul>
<h1 id="heading-when-indexes-are-worth-it"> When Indexes Are Worth It</h1>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Scenario</td><td>Index</td></tr>
</thead>
<tbody>
<tr>
<td>High selectivity</td><td></td></tr>
<tr>
<td>Read-heavy</td><td></td></tr>
<tr>
<td>Stable data</td><td></td></tr>
<tr>
<td>Covering index</td><td></td></tr>
<tr>
<td>OLAP workloads</td><td></td></tr>
</tbody>
</table>
</div><h2 id="heading-covering-index-the-only-free-ish-one"> Covering Index (The Only Free-ish One)</h2>
<pre><code class="lang-sql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">INDEX</span> idx_user_email_name
<span class="hljs-keyword">ON</span> <span class="hljs-keyword">users</span>(email, <span class="hljs-keyword">name</span>);
</code></pre>
<p>Query:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">SELECT</span> <span class="hljs-keyword">name</span> <span class="hljs-keyword">FROM</span> <span class="hljs-keyword">users</span> <span class="hljs-keyword">WHERE</span> email = ?;
</code></pre>
<p> No table lookup<br /> Reduced read amplification</p>
<h2 id="heading-how-this-connects-to-previous-blogs">🔥 How This Connects to Previous Blogs</h2>
<ul>
<li><p><a target="_blank" href="https://www.lldcoding.com/read-amplification-vs-write-amplification"><strong>Read Amplification</strong></a>  indexes dont eliminate it</p>
</li>
<li><p><a target="_blank" href="https://www.lldcoding.com/read-amplification-vs-write-amplification"><strong>Write Amplification</strong></a>  indexes multiply it</p>
</li>
<li><p><a target="_blank" href="https://www.lldcoding.com/when-one-key-becomes-a-bottleneck-solving-the-hot-key-problem"><strong>Hot Keys</strong></a>  hot index pages become bottlenecks</p>
</li>
<li><p><strong>P99 latency</strong>  index rebalancing spikes</p>
</li>
</ul>
]]></description><link>https://lldcoding.com/why-indexes-are-not-free</link><guid isPermaLink="true">https://lldcoding.com/why-indexes-are-not-free</guid><category><![CDATA[General Programming]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Java]]></category><category><![CDATA[Python]]></category><category><![CDATA[interview]]></category><category><![CDATA[concurrency]]></category><category><![CDATA[Databases]]></category><category><![CDATA[learning]]></category><dc:creator><![CDATA[Subhahu Jain]]></dc:creator></item><item><title><![CDATA[🎤 Live Podcast with Guests — Concurrency Problem]]></title><description><![CDATA[<h3 id="heading-real-world-scenario">🧠 Real-World Scenario</h3>
<p>Youre building a <strong>live podcast platform</strong> where:</p>
<ul>
<li><p>A <strong>host</strong> starts a live podcast session.</p>
</li>
<li><p>Multiple <strong>guests</strong> are invited to join.</p>
</li>
<li><p>The podcast <strong>must not start</strong> until <strong>all required guests have joined</strong>.</p>
</li>
<li><p>Guests may join at <strong>different times</strong>.</p>
</li>
<li><p>Everything happens <strong>concurrently</strong> (over the network, different threads).</p>
</li>
</ul>
<h2 id="heading-what-exactly-is-the-problem">📌 What Exactly Is the Problem?</h2>
<p>We have <strong>dependencies between tasks</strong>:</p>
<ul>
<li><p>Each <strong>guest joining</strong> is an independent task.</p>
</li>
<li><p>The <strong>host starting the podcast</strong> depends on <em>all guests being present</em>.</p>
</li>
</ul>
<p>👉 This creates a <strong>synchronization problem</strong>:</p>
<blockquote>
<p><em>One thread must wait until several other threads finish their work.</em></p>
</blockquote>
<h2 id="heading-mapping-to-concurrency-concepts">🧩 Mapping to Concurrency Concepts</h2>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Real World</strong></td><td><strong>Concurrency</strong></td></tr>
</thead>
<tbody>
<tr>
<td>Guest joining</td><td>Worker thread</td></tr>
<tr>
<td>Host waiting</td><td>Main / coordinator thread</td></tr>
<tr>
<td>All guests joined</td><td>Synchronization condition</td></tr>
<tr>
<td>Live podcast starts</td><td>Final action after coordination</td></tr>
</tbody>
</table>
</div><h2 id="heading-timeline-example">🕒 Timeline Example</h2>
<p>Imagine:</p>
<ul>
<li><p>Podcast needs <strong>3 guests</strong>.</p>
</li>
<li><p>Guests join at different times.</p>
</li>
</ul>
<pre><code class="lang-css"><span class="hljs-selector-tag">Time</span> 
<span class="hljs-selector-tag">Guest</span> 1 <span class="hljs-selector-tag">joins</span> 
<span class="hljs-selector-tag">Guest</span> 2 <span class="hljs-selector-tag">joins</span>     
<span class="hljs-selector-tag">Guest</span> 3 <span class="hljs-selector-tag">joins</span> 
                              
                 🎤 <span class="hljs-selector-tag">Podcast</span> <span class="hljs-selector-tag">Starts</span>
</code></pre>
<p>The <strong>host cannot start early</strong>, even if:</p>
<ul>
<li><p>1 guest joins</p>
</li>
<li><p>2 guests join</p>
</li>
</ul>
<p>The host must wait for <strong>all 3</strong>.</p>
<h2 id="heading-why-this-is-a-concurrency-problem">🚨 Why This Is a Concurrency Problem</h2>
<h3 id="heading-naive-thinking-wrong"> Naive Thinking (Wrong)</h3>
<blockquote>
<p>Just start the podcast when guests arrive.</p>
</blockquote>
<p>Problems:</p>
<ul>
<li><p>Host might start before everyone joins.</p>
</li>
<li><p>Host might check are guests ready? while guests are still joining.</p>
</li>
<li><p>Leads to <strong>race conditions</strong>:</p>
<ul>
<li><p>Host checks  sees only 2 guests  waits</p>
</li>
<li><p>Guest 3 joins immediately after  host never notices</p>
</li>
</ul>
</li>
</ul>
<h2 id="heading-core-challenges"> Core Challenges</h2>
<ol>
<li><p><strong>Ordering</strong></p>
<ul>
<li>Guests can join in <em>any order</em>.</li>
</ul>
</li>
<li><p><strong>Timing</strong></p>
<ul>
<li>Guests join at unpredictable times.</li>
</ul>
</li>
<li><p><strong>Coordination</strong></p>
<ul>
<li>Host must wait, but not forever.</li>
</ul>
</li>
<li><p><strong>Correctness</strong></p>
<ul>
<li>Podcast must start <strong>exactly once</strong>.</li>
</ul>
</li>
<li><p><strong>Scalability</strong></p>
<ul>
<li>Works for 2 guests, 10 guests, or 100 guests.</li>
</ul>
</li>
</ol>
<h2 id="heading-what-makes-this-problem-special">🧠 What Makes This Problem Special?</h2>
<p>This is <strong>not about sharing data</strong> (like counters or money).<br />This is about <strong>waiting for conditions</strong>.</p>
<p>It belongs to a special class of concurrency problems:</p>
<h3 id="heading-wait-until-n-things-are-done">🔹 <em>Wait until N things are done</em></h3>
<p>Examples:</p>
<ul>
<li><p>App startup waits for DB + Cache + Config</p>
</li>
<li><p>Game waits for all players to be ready</p>
</li>
<li><p>Deployment waits for all services to be healthy</p>
</li>
<li><p>Podcast waits for all guests to join 🎤</p>
</li>
</ul>
<h2 id="heading-key-question-the-system-must-answer">🧪 Key Question the System Must Answer</h2>
<blockquote>
<p><strong>How does one thread know that all other threads are done?</strong></p>
</blockquote>
<p>Thats the <strong>heart of the problem</strong>.</p>
<h2 id="heading-solutions">Solutions</h2>
<ol>
<li><h2 id="heading-naive-solution-looks-correct-actually-broken"><strong>Naive Solution (Looks Correct, Actually Broken)</strong></h2>
</li>
</ol>
<h3 id="heading-naive-idea">🧠 Naive Idea</h3>
<ul>
<li><p>Keep a <strong>counter</strong> of guests who have joined.</p>
</li>
<li><p>Host checks the counter.</p>
</li>
<li><p>If count == required guests  start podcast.</p>
</li>
</ul>
<h3 id="heading-naive-code-conceptual"> Naive Code (Conceptual)</h3>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Podcast</span> </span>{
    <span class="hljs-keyword">int</span> requiredGuests = <span class="hljs-number">3</span>;
    <span class="hljs-keyword">int</span> joinedGuests = <span class="hljs-number">0</span>;

    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">guestJoins</span><span class="hljs-params">()</span> </span>{
        joinedGuests++;
        System.out.println(<span class="hljs-string">"Guest joined. Total = "</span> + joinedGuests);
    }

    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">hostStarts</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">while</span> (joinedGuests &lt; requiredGuests) {
            <span class="hljs-comment">// wait</span>
        }
        System.out.println(<span class="hljs-string">"🎤 Podcast started!"</span>);
    }
}
</code></pre>
<h2 id="heading-why-this-fails-concurrency-problems"><strong>Why This Fails (Concurrency Problems)</strong></h2>
<h3 id="heading-problem-1-busy-waiting-cpu-waste">🚨 Problem 1: <strong>Busy Waiting (CPU Waste)</strong></h3>
<ul>
<li><p>Host thread spins endlessly checking the condition.</p>
</li>
<li><p>Wastes CPU cycles.</p>
</li>
<li><p>Scales terribly.</p>
</li>
</ul>
<h3 id="heading-problem-2-visibility-problem">🚨 Problem 2: <strong>Visibility Problem</strong></h3>
<p>Even worse  <strong>this may never work</strong>.</p>
<p><strong>Why?</strong></p>
<ul>
<li><p><code>joinedGuests</code> is <strong>not volatile</strong></p>
</li>
<li><p>Host thread may never see updates from guest threads.</p>
</li>
</ul>
<p>📌 Host might loop <strong>forever</strong>, even after all guests join.</p>
<h3 id="heading-problem-3-race-condition">🚨 Problem 3: <strong>Race Condition</strong></h3>
<p>Two guests join at the same time:</p>
<pre><code class="lang-javascript">Thread A reads joinedGuests = <span class="hljs-number">1</span>
Thread B reads joinedGuests = <span class="hljs-number">1</span>
Thread A writes joinedGuests = <span class="hljs-number">2</span>
Thread B writes joinedGuests = <span class="hljs-number">2</span>  
</code></pre>
<p>One join is <strong>lost</strong>.</p>
<h3 id="heading-problem-4-podcast-may-start-multiple-times">🚨 Problem 4: <strong>Podcast May Start Multiple Times</strong></h3>
<p>If multiple host threads exist:</p>
<ul>
<li><p>All see <code>joinedGuests == requiredGuests</code></p>
</li>
<li><p>All start the podcast</p>
</li>
</ul>
<p>💥 Multiple starts = disaster.</p>
<h2 id="heading-first-fix-attempt-add-synchronized"><strong> First Fix Attempt  Add</strong> <code>synchronized</code></h2>
<h3 id="heading-improved-but-still-ugly">Improved but Still Ugly</h3>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Podcast</span> </span>{
    <span class="hljs-keyword">int</span> requiredGuests = <span class="hljs-number">3</span>;
    <span class="hljs-keyword">int</span> joinedGuests = <span class="hljs-number">0</span>;

    <span class="hljs-function"><span class="hljs-keyword">synchronized</span> <span class="hljs-keyword">void</span> <span class="hljs-title">guestJoins</span><span class="hljs-params">()</span> </span>{
        joinedGuests++;
        System.out.println(<span class="hljs-string">"Guest joined. Total = "</span> + joinedGuests);
    }

    <span class="hljs-function"><span class="hljs-keyword">synchronized</span> <span class="hljs-keyword">void</span> <span class="hljs-title">hostStarts</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">while</span> (joinedGuests &lt; requiredGuests) {
            <span class="hljs-comment">// still waiting</span>
        }
        System.out.println(<span class="hljs-string">"🎤 Podcast started!"</span>);
    }
}
</code></pre>
<h2 id="heading-why-this-still-fails"><strong>Why This Still Fails</strong></h2>
<h3 id="heading-problem-1-host-holds-the-lock">🚨 Problem 1: <strong>Host Holds the Lock</strong></h3>
<ul>
<li><p>Host enters <code>hostStarts()</code> and holds the lock.</p>
</li>
<li><p>Guests can <strong>never enter</strong> <code>guestJoins()</code>.</p>
</li>
<li><p>Deadlock-like behavior.</p>
</li>
</ul>
<h3 id="heading-problem-2-still-busy-waiting">🚨 Problem 2: <strong>Still Busy Waiting</strong></h3>
<ul>
<li><p>CPU burn continues.</p>
</li>
<li><p>No proper waiting mechanism.</p>
</li>
</ul>
<h2 id="heading-realization-key-insight"><strong>Realization (Key Insight)</strong></h2>
<p>We dont want:</p>
<ul>
<li><p>Polling</p>
</li>
<li><p>Spinning</p>
</li>
<li><p>Manual checking</p>
</li>
</ul>
<p>We want:</p>
<blockquote>
<p><strong>Host sleeps until the last guest arrives, then wakes up exactly once.</strong></p>
</blockquote>
<p>This is a <strong>coordination problem</strong>, not a data-sharing problem.</p>
<h2 id="heading-correct-mental-model"><strong>Correct Mental Model</strong></h2>
<ul>
<li><p>Each guest says:<br />  <strong>Im ready.</strong></p>
</li>
<li><p>Host says:<br />  <strong>Wake me up when everyone is ready.</strong></p>
</li>
</ul>
<p>This maps perfectly to:</p>
<blockquote>
<p>🧰 <strong>CountDownLatch</strong></p>
</blockquote>
<h2 id="heading-correct-solution"><strong>Correct Solution</strong></h2>
<p>Already covered in our <a target="_blank" href="https://interview.lldcoding.com/dashboard/course1?chapter=%5BNEW%5D+%F0%9F%8E%A4+Live+Podcast+with+Guests+%E2%80%94+Concurrency+Problem-L2FwaS9jb250ZW50L2xpdmUtcG9kY2FzdC1Db25jdXJyZW5jeS1Qcm9ibGVtLmNodW5rMC5lbmNyeXB0ZWQ%3D">premium course.</a></p>
]]></description><link>https://lldcoding.com/live-podcast-with-guests-concurrency-problem</link><guid isPermaLink="true">https://lldcoding.com/live-podcast-with-guests-concurrency-problem</guid><category><![CDATA[General Programming]]></category><category><![CDATA[concurrency]]></category><category><![CDATA[interview]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Java]]></category><category><![CDATA[Python]]></category><dc:creator><![CDATA[Subhahu Jain]]></dc:creator></item><item><title><![CDATA[[Uber] Design 🏢(LLD)  Meeting Scheduler - Machine Coding Interview]]></title><description><![CDATA[<p>We are designing a meeting scheduler with the following requirements:</p>
<ol>
<li><p>There are N rooms.</p>
</li>
<li><p>We are given a stream of meeting requests (start time, end time, capacity).</p>
</li>
<li><p>We have to assign a room to the meeting if available, considering:</p>
<ul>
<li><p>The room must be free during the requested time.</p>
</li>
<li><p>The room must have at least the required capacity.</p>
</li>
</ul>
</li>
<li><p>We must minimize spillage of free time (i.e., use the room that has the least free time that can accommodate the meeting).</p>
</li>
<li><p>We have to store audit logs for each room (when a meeting is scheduled, etc.) and delete audit logs after X days.</p>
</li>
</ol>
<p><strong>Additional considerations:</strong></p>
<ul>
<li>Concurrency: multiple requests may come in simultaneously.</li>
</ul>
<h3 id="heading-solutionapproaches"><strong>Solution/Approaches</strong></h3>
<p><em>Core LLD Components</em></p>
<ol>
<li><p><strong>Room Management</strong></p>
<ol>
<li><pre><code class="lang-java"> <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Room</span> </span>{
     <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> String roomId;
     <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> capacity;
     <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> NavigableMap&lt;LocalDateTime, Interval&gt; bookings; <span class="hljs-comment">// TreeMap for sorted intervals</span>
     <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> ReentrantReadWriteLock rwLock;

     <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Room</span><span class="hljs-params">(String roomId, <span class="hljs-keyword">int</span> capacity)</span> </span>{
         <span class="hljs-keyword">this</span>.roomId = roomId;
         <span class="hljs-keyword">this</span>.capacity = capacity;
         <span class="hljs-keyword">this</span>.bookings = <span class="hljs-keyword">new</span> TreeMap&lt;&gt;();
         <span class="hljs-keyword">this</span>.rwLock = <span class="hljs-keyword">new</span> ReentrantReadWriteLock(<span class="hljs-keyword">true</span>); <span class="hljs-comment">// Fair lock</span>
     }

     <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">isAvailable</span><span class="hljs-params">(Interval requested)</span> </span>{
         rwLock.readLock().lock();
         <span class="hljs-keyword">try</span> {
             <span class="hljs-comment">// Check using interval tree or binary search</span>
             Entry&lt;LocalDateTime, Interval&gt; floor = bookings.floorEntry(requested.getStart());
             Entry&lt;LocalDateTime, Interval&gt; ceiling = bookings.ceilingEntry(requested.getStart());

             <span class="hljs-keyword">return</span> !conflictsWith(floor, requested) &amp;&amp; !conflictsWith(ceiling, requested);
         } <span class="hljs-keyword">finally</span> {
             rwLock.readLock().unlock();
         }
     }

     <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">conflictsWith</span><span class="hljs-params">(Entry&lt;LocalDateTime, Interval&gt; existing, Interval requested)</span> </span>{
         <span class="hljs-keyword">return</span> existing != <span class="hljs-keyword">null</span> &amp;&amp; existing.getValue().overlaps(requested);
     }
 }
</code></pre>
</li>
</ol>
</li>
<li><p><strong>Interval Management</strong></p>
<ol>
<li><pre><code class="lang-java"> <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Interval</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Comparable</span>&lt;<span class="hljs-title">Interval</span>&gt; </span>{
     <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> LocalDateTime start;
     <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> LocalDateTime end;

     <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">overlaps</span><span class="hljs-params">(Interval other)</span> </span>{
         <span class="hljs-keyword">return</span> !(<span class="hljs-keyword">this</span>.end.isBefore(other.start) || <span class="hljs-keyword">this</span>.start.isAfter(other.end));
     }

     <span class="hljs-comment">// Calculate spillage when this interval is inserted into existing intervals</span>
     <span class="hljs-function"><span class="hljs-keyword">public</span> Duration <span class="hljs-title">calculateSpillage</span><span class="hljs-params">(List&lt;Interval&gt; existingIntervals)</span> </span>{
         List&lt;Interval&gt; merged = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;(existingIntervals);
         merged.add(<span class="hljs-keyword">this</span>);
         Collections.sort(merged);

         Duration spillage = Duration.ZERO;
         <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; merged.size() - <span class="hljs-number">1</span>; i++) {
             Duration gap = Duration.between(merged.get(i).getEnd(), merged.get(i + <span class="hljs-number">1</span>).getStart());
             <span class="hljs-keyword">if</span> (!gap.isNegative() &amp;&amp; !gap.isZero()) {
                 spillage = spillage.plus(gap);
             }
         }
         <span class="hljs-keyword">return</span> spillage;
     }
 }
</code></pre>
</li>
</ol>
</li>
<li><p><strong>Meeting Scheduler Core</strong></p>
<ol>
<li><pre><code class="lang-java"> <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MeetingScheduler</span> </span>{
     <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> List&lt;Room&gt; rooms;
     <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> Map&lt;String, Room&gt; roomMap;
     <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> AuditLogger auditLogger;
     <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> SpillageOptimizer spillageOptimizer;

     <span class="hljs-comment">// Different scheduling strategies</span>
     <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">enum</span> <span class="hljs-title">SchedulingStrategy</span> </span>{
         MIN_SPILLAGE,
         BEST_FIT_CAPACITY,
         ROUND_ROBIN,
         LEAST_UTILIZED
     }

     <span class="hljs-function"><span class="hljs-keyword">public</span> Optional&lt;String&gt; <span class="hljs-title">scheduleMeeting</span><span class="hljs-params">(MeetingRequest request)</span> </span>{
         List&lt;CandidateRoom&gt; candidates = findCandidateRooms(request);

         <span class="hljs-keyword">if</span> (candidates.isEmpty()) {
             <span class="hljs-keyword">return</span> Optional.empty();
         }

         <span class="hljs-comment">// Apply optimization strategy</span>
         CandidateRoom selected = spillageOptimizer.selectRoom(candidates, request);

         <span class="hljs-comment">// Attempt to book with optimistic locking</span>
         <span class="hljs-keyword">return</span> attemptBookingWithRetry(selected, request);
     }

     <span class="hljs-function"><span class="hljs-keyword">private</span> List&lt;CandidateRoom&gt; <span class="hljs-title">findCandidateRooms</span><span class="hljs-params">(MeetingRequest request)</span> </span>{
         List&lt;CandidateRoom&gt; candidates = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();

         <span class="hljs-keyword">for</span> (Room room : rooms) {
             <span class="hljs-keyword">if</span> (room.getCapacity() &gt;= request.getCapacity()) {
                 <span class="hljs-keyword">if</span> (room.isAvailable(request.getInterval())) {
                     <span class="hljs-keyword">double</span> spillage = calculateSpillageForRoom(room, request);
                     candidates.add(<span class="hljs-keyword">new</span> CandidateRoom(room, spillage));
                 }
             }
         }
         <span class="hljs-keyword">return</span> candidates;
     }
 }
</code></pre>
</li>
</ol>
</li>
</ol>
<h3 id="heading-kio">**</h3>
<p>Gaps / issues in design**</p>
<ol>
<li><p><strong>Too much logic in</strong> <code>MeetingScheduler</code></p>
<ul>
<li><p><code>findCandidateRooms</code> is doing filtering + availability + spillage calculation.</p>
</li>
<li><p>Could be moved into:</p>
<ul>
<li><p><code>RoomSelector</code> / <code>CandidateFinder</code>, or</p>
</li>
<li><p>At least a separate component responsible for candidate discovery.</p>
</li>
</ul>
</li>
</ul>
</li>
<li><p><strong>Enum</strong> <code>SchedulingStrategy</code> not wired in</p>
<ul>
<li><p>Enum is declared but not used in <code>scheduleMeeting</code>; ideally <code>SpillageOptimizer</code> should be a family of strategies.</p>
</li>
<li><p>Better: <code>Map&lt;SchedulingStrategy, SchedulingStrategyHandler&gt;</code> or <code>StrategyFactory</code>.</p>
</li>
</ul>
</li>
<li><p><strong>Data structure for rooms</strong></p>
<ul>
<li><p>Assumes a simple <code>List&lt;Room&gt;</code> scan.</p>
</li>
<li><p>For big systems, would need:</p>
<ul>
<li><p>Indexing by capacity,</p>
</li>
<li><p>Indexing by building / floor / equipment,</p>
</li>
<li><p>Sharding across nodes.</p>
</li>
</ul>
</li>
</ul>
</li>
</ol>
<h3 id="heading-concurrency-issues-in-this-design">Concurrency issues in this design</h3>
<p>Assume multiple threads calling <code>scheduleMeeting</code> simultaneously.</p>
<p><strong>a) Check-then-act race on availability</strong></p>
<p>Problem area:</p>
<pre><code class="lang-java"><span class="hljs-keyword">if</span> (room.isAvailable(request.getInterval())) {
    <span class="hljs-keyword">double</span> spillage = calculateSpillageForRoom(room, request);
    candidates.add(<span class="hljs-keyword">new</span> CandidateRoom(room, spillage));
}
</code></pre>
<p>Then later:</p>
<pre><code class="lang-java"><span class="hljs-keyword">return</span> attemptBookingWithRetry(selected, request);
</code></pre>
<p>Between <code>isAvailable()</code> and the actual booking:</p>
<ul>
<li><p>Another thread might book the same room for overlapping interval.</p>
</li>
<li><p>Both threads saw <code>available == true</code>  <strong>double booking</strong> risk.</p>
</li>
</ul>
<p><strong>b) Non-thread-safe data structures</strong></p>
<ul>
<li><p><code>List&lt;Room&gt; rooms;</code></p>
</li>
<li><p><code>Map&lt;String, Room&gt; roomMap;</code></p>
</li>
</ul>
<p>If rooms can be added/removed at runtime:</p>
<ul>
<li>Concurrent modification without synchronization  <code>ConcurrentModificationException</code> or stale views.</li>
</ul>
<p>Even if the list itself is not mutated, <code>Room</code> internals (its schedule) are mutable and accessed from multiple threads  must be made thread-safe.</p>
<p><strong>c) Lost updates on room schedule</strong></p>
<p>Room schedule is some structure (e.g., <code>List&lt;Booking&gt;</code>) inside <code>Room</code>.</p>
<ul>
<li><p>If two threads call <code>room.addBooking(...)</code> simultaneously without proper synchronization:</p>
<ul>
<li>The underlying list / tree can be corrupted or some booking updates can be lost.</li>
</ul>
</li>
</ul>
<p><strong>d) Thundering herd around popular time slots</strong></p>
<p>If many users try to book for the same popular time:</p>
<ul>
<li><p>Lots of threads will compute candidates, all select the same best room, and then race to book it.</p>
</li>
<li><p>Without control, this causes many retries/failures.</p>
</li>
</ul>
<h3 id="heading-concurrency-control-patterns-to-use">Concurrency control patterns to use</h3>
<p>Will be covered in our <a target="_blank" href="https://interview.lldcoding.com/">course</a>.</p>
<h3 id="heading-improved-code-version">Improved Code Version</h3>
<p>Will be covered in our <a target="_blank" href="https://interview.lldcoding.com/">course</a>.</p>
]]></description><link>https://lldcoding.com/uber-design-lld-meeting-scheduler-machine-coding-interview</link><guid isPermaLink="true">https://lldcoding.com/uber-design-lld-meeting-scheduler-machine-coding-interview</guid><category><![CDATA[General Programming]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[Java]]></category><category><![CDATA[interview]]></category><category><![CDATA[Low Code]]></category><dc:creator><![CDATA[Subhahu Jain]]></dc:creator></item><item><title><![CDATA[Multi-Threaded Parentheses Validator]]></title><description><![CDATA[<h3 id="heading-problem-parallel-parentheses-validator">Problem: Parallel Parentheses Validator</h3>
<h4 id="heading-description">Description</h4>
<p>You are given a string <code>s</code> of length <code>N</code> consisting only of the characters <code>'('</code> and <code>')'</code>. A parentheses string is considered <strong>valid</strong> if:</p>
<ol>
<li><p>Every <code>'('</code> has a matching <code>')'</code> to its right.</p>
</li>
<li><p>No prefix of the string contains more <code>')'</code> than <code>'('</code>.</p>
</li>
</ol>
<p>Write a function:</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">boolean</span> <span class="hljs-title">isValidParallel</span><span class="hljs-params">(String s, <span class="hljs-keyword">int</span> P)</span></span>
</code></pre>
<p>that determines whether <code>s</code> is valid, using <code>P</code> worker threads. Each thread can only read a disjoint substring of <code>s</code>.</p>
<h2 id="heading-solution">Solution</h2>
<ol>
<li><h3 id="heading-sequential-approach">Sequential Approach</h3>
</li>
</ol>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">isValidSequential</span><span class="hljs-params">(String s)</span> </span>{
    <span class="hljs-keyword">int</span> balance = <span class="hljs-number">0</span>;
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; s.length(); i++) {
        <span class="hljs-keyword">if</span> (s.charAt(i) == <span class="hljs-string">'('</span>) {
            balance++;
        } <span class="hljs-keyword">else</span> {
            balance--;
        }
        <span class="hljs-keyword">if</span> (balance &lt; <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>;
    }
    <span class="hljs-keyword">return</span> balance == <span class="hljs-number">0</span>;
}
</code></pre>
<p>What is working here</p>
<ul>
<li><p>Simple and straightforward</p>
</li>
<li><p>O(N) time complexity</p>
</li>
<li><p>O(1) space complexity</p>
</li>
<li><p>Easy to understand and debug</p>
</li>
</ul>
<p>Drawbacks</p>
<ul>
<li><p>Cannot utilize multiple threads</p>
</li>
<li><p>Doesn't meet the problem requirements for parallel processing</p>
</li>
<li><p>Would be slow for extremely large strings</p>
</li>
</ul>
<ol start="2">
<li><h3 id="heading-naive-parallel-approach-problematic">Naive Parallel Approach (Problematic)</h3>
</li>
</ol>
<pre><code class="lang-java"><span class="hljs-comment">// This approach doesn't work - just for discussion</span>
<span class="hljs-function"><span class="hljs-keyword">boolean</span> <span class="hljs-title">isValidNaiveParallel</span><span class="hljs-params">(String s, <span class="hljs-keyword">int</span> P)</span> </span>{
    ExecutorService executor = Executors.newFixedThreadPool(P);
    <span class="hljs-keyword">int</span> segmentSize = s.length() / P;
    Future&lt;Boolean&gt;[] futures = <span class="hljs-keyword">new</span> Future[P];

    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; P; i++) {
        <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> start = i * segmentSize;
        <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> end = (i == P-<span class="hljs-number">1</span>) ? s.length() : start + segmentSize;

        futures[i] = executor.submit(() -&gt; {
            <span class="hljs-keyword">return</span> isValidSequential(s.substring(start, end));
        });
    }

    <span class="hljs-comment">// Collect results</span>
    <span class="hljs-keyword">for</span> (Future&lt;Boolean&gt; future : futures) {
        <span class="hljs-keyword">if</span> (!future.get()) <span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>;
    }
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;
}
</code></pre>
<p><strong>Why this fails:</strong></p>
<ul>
<li><p>Each segment is validated independently, but validity depends on the entire prefix</p>
</li>
<li><p>A segment might be locally valid but globally invalid due to balance dependencies</p>
</li>
<li><p>Example: <code>"())("</code> split as <code>"())"</code> and <code>"("</code> - both segments fail local validation, but the real issue is global</p>
</li>
</ul>
<ol start="3">
<li><h3 id="heading-better-parallel-approach-the-working-solution">Better Parallel Approach (The Working Solution)</h3>
</li>
</ol>
<pre><code class="lang-java"><span class="hljs-keyword">static</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SegmentResult</span> </span>{
    <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> netBalance;
    <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> minBalance;

    SegmentResult(<span class="hljs-keyword">int</span> net, <span class="hljs-keyword">int</span> min) {
        <span class="hljs-keyword">this</span>.netBalance = net;
        <span class="hljs-keyword">this</span>.minBalance = min;
    }
}

<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">isValidParallel</span><span class="hljs-params">(String s, <span class="hljs-keyword">int</span> P)</span> </span>{
    <span class="hljs-comment">// ... thread pool setup</span>

    <span class="hljs-comment">// Each thread processes its segment</span>
    Future&lt;SegmentResult&gt;[] futures = <span class="hljs-keyword">new</span> Future[P];
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; P; i++) {
        <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> start = i * segmentSize;
        <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> end = Math.min(start + segmentSize, n);
        futures[i] = executor.submit(() -&gt; processSegment(s, start, end));
    }

    <span class="hljs-comment">// Sequential combination</span>
    <span class="hljs-keyword">int</span> currentBalance = <span class="hljs-number">0</span>;
    <span class="hljs-keyword">int</span> globalMinBalance = <span class="hljs-number">0</span>;

    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; P; i++) {
        SegmentResult result = futures[i].get();
        globalMinBalance = Math.min(globalMinBalance, currentBalance + result.minBalance);
        currentBalance += result.netBalance;
    }

    <span class="hljs-keyword">return</span> globalMinBalance &gt;= <span class="hljs-number">0</span> &amp;&amp; currentBalance == <span class="hljs-number">0</span>;
}
</code></pre>
<p>This solution is great, but but what if <strong><em>we have very large P.</em></strong></p>
<h3 id="heading-solution-4">Solution 4</h3>
<p>Will be covered in our <a target="_blank" href="https://interview.lldcoding.com/">course</a>.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/Z9NUV44LAu8">https://youtu.be/Z9NUV44LAu8</a></div>
]]></description><link>https://lldcoding.com/multi-threaded-parentheses-validator</link><guid isPermaLink="true">https://lldcoding.com/multi-threaded-parentheses-validator</guid><category><![CDATA[Programming Blogs]]></category><category><![CDATA[General Programming]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Java]]></category><category><![CDATA[C++]]></category><category><![CDATA[Python]]></category><dc:creator><![CDATA[Subhahu Jain]]></dc:creator></item><item><title><![CDATA[Design (LLD) Paytm/Phone Wallet System - Machine Coding]]></title><description><![CDATA[<p><strong>Asked in Phonepe interview.</strong></p>
<p>Design and implement a <strong>Paytm/PhonePe Wallet System</strong> that supports multiple concurrent users performing transactions at the same time. Your system should:</p>
<p><img src="https://kroki.io/d2/svg/eNq9VE2P2jAQvfMrRtkLeyAsH0t3OVRKk9BSpVu6AfW4cpJJsDA2dQxtVPHf6yQEwseitlLrQ5QZf7znmfccUYmhooIPQdJkrhobItMh_GwARN1WKHhMkzIEYCQTa9VCnlCOQ4hIIlFPbBvbRmOWohyCYa1WkP8axZZ0TlZ64QplKngeq4xhdVqqpFjoyLgZ3JH7mBhFNhZcaVgm5OlMIFg0BCXXe8yvhDFUfpYqXOrVZQg-yg0NEZofyYa0_ZWkPLnd8anjx5SxHGM0sjqdgXHC6bFPesHDJU53xbjISX_GES5XQiEPM724FoFHsqou-8rktSc8YbhDr9E7EIyLYeyyR5BlQkYoW5JEdK07d1-ktxWf6Q_-iXCSFN2ZSsJTUrQbdtn_SShXUID5EZYSSxqCgwFVbVtiRJVRMfYVUXkLPBpjmIUM_xnVY04T98kZP72H1lvwZ7bt-n57ZI091zEqvTlEkYCkObmJSJVWv__Fg6Zlj53bI8GHGaNc1-A1yXWw-9gLLomrzvdEXAClwNOD1KckYJgv9jA67_AHmiohMyOnfgP1mRET3wvH5petu8g8lm_HLLfFKJtaSC9j58V6Z18y02UzE06Xupn1ml93cR3_jNuRlLsmzDj9tkaw5xgurlK64thT_ANGDl9reM8E3_Vcewqjz88wmzjW1IWmJ8LFK8_LAT7uv-kGgz-oSAV7VoHKGn0TnjFdM3UVt08ifPi9axcH129s7hV1b4J-1JFHpTGXyP8e9RfbLeL8" alt class="image--center mx-auto" /></p>
<h3 id="heading-features-required"> Features Required</h3>
<ol>
<li><p><strong>User &amp; Wallet Management</strong></p>
<ul>
<li><p>Each user has a unique wallet with balance.</p>
</li>
<li><p>Support wallet creation and balance inquiry.</p>
</li>
</ul>
</li>
<li><p><strong>Concurrent Transactions</strong></p>
<ul>
<li><p>Add money to wallet (via UPI, Card, NetBanking).</p>
</li>
<li><p>Send money from one wallet to another.</p>
</li>
<li><p>Handle concurrent deposits and transfers without race conditions.</p>
</li>
</ul>
</li>
<li><p><strong>Transaction Lifecycle</strong></p>
<ul>
<li><p>Each transaction can be <code>PENDING  SUCCESS / FAILED / REVERSED</code>.</p>
</li>
<li><p>Ensure <strong>atomic debit/credit</strong> (no money disappears or duplicates even under concurrency).</p>
</li>
</ul>
</li>
<li><p><strong>Transaction Reliability</strong></p>
<ul>
<li><p>Idempotency (retries should not cause double debit).</p>
</li>
<li><p>Refund logic (if debit succeeds but credit fails, rollback debit).</p>
</li>
</ul>
</li>
<li><p><strong>Transaction History</strong></p>
<ul>
<li><p>Maintain mini-statement per user.</p>
</li>
<li><p>Show in descending order of time (latest first).</p>
</li>
</ul>
</li>
</ol>
<h2 id="heading-solution-approaches"><strong>Solution approaches</strong></h2>
<h3 id="heading-design-patterns-to-use">🔑 Design Patterns to Use</h3>
<p><img src="https://kroki.io/d2/svg/eNqVVEtz2jAQvvtXaJxLe4DhVRo4dMYQQ5jhNdik06Ow10aNkagkJ2E6-e_VynZNUpJOOGB5V97d7yHFTEKkmeBDEotH7jxQqYbkt0NI3GlEgicsLV4JyehJ5LoBPGUczHaaSjCJZ-fZca5Iu0nCW5-MN74XzlZLb07m3g9_40xopIU8DYkbSsoVtc1IGXVtaaVPGVRdEpZlZvPVZOK1233XxpSW4h4wOujR7u66iCaCazNiJiRmWvZXZHYii4dEy7yYD0ffAVYt25I11RqkwTyWQDUoEj5xstr9NFQoF_EsKKcpyFdTl9Fy6j09Ig2MHgSP34LRhs6gu7s0cGJ__xk4YDzNQKM8Y-Ba0oyMhZAx49QAcQvqOwX1I__Wu5utNhX15JP_BFGOk392vgt5n2Ti8RWiEA7HzDDwjhDnc9ZC9Fv0S0LPo41HFuv9kPQuI7qjGYtNJ_OxsUr1hgWKKTFhgJQvZC5SFmE20FTnxpJut0m2R_ymDGFyKTRL0Fu9ZrkuKTGb1_PtdOqN5j4Jwo0X-tOZHziTnBvuUrRCsTLFpKmZvmfFpJUM_mWg1e0PaPsN_bbrmdlj_uv6Jjqm0mxz8fEivgQ9ovzepMrVi8EKRAZhEBoYxFvekNUo8Dd39qA5yAa8ktXGXtgUTzlFL31M5qT3tbPrXwCJrzIG2ZA0ZqhPu1VCX0NF8dpf3syWU6tiHkWgUMZgOx77QYDBCWUZICETbzb3byzQ1U6BfAC8hFyrKItoAemkNBzeUalHY7huffhqCBYBTrUISGAas8hacp2rPQIwjzpsZdhAZudRe3ZU1TVBGt9Ifc9t4FcOSpf3iVvdgLjp7BTOuDKCaGYPQRVvVvbHgn-tWjmhvra2ypwCyEx5iMkC9F7EZ8w0L5m0yFDODqZWRcFz3bk4VNi4MpR91j2tvxhiv9yqtkqROWP6rE1xSrHNudLVuu42koLGEVX6crNa7Mu4_gAHvhFb" alt class="image--center mx-auto" /></p>
<ol>
<li><p><strong>Strategy Pattern</strong>  Different funding sources (UPI/Card/NetBanking).</p>
<ol>
<li><p><strong>Why Strategy?</strong></p>
<ul>
<li><p>Each payment source (UPI, Card, NetBanking) has the same <em>high-level goal</em> (fund wallet) but <em>different implementation</em>.</p>
</li>
<li><p>We want to swap/add new methods without modifying existing code.</p>
</li>
</ul>
</li>
<li><p><strong>Why not Adapter?</strong></p>
<ul>
<li><p>Adapter is for integrating third-party APIs with different interfaces.</p>
</li>
<li><p>Here, we control the implementation; we dont need to adapt legacy/external code.</p>
</li>
</ul>
</li>
<li><p><strong>Why not Bridge?</strong></p>
<ul>
<li>Bridge separates abstraction from implementation. Overkill here because abstraction (payment) and implementation (different sources) are already cleanly separated.</li>
</ul>
</li>
</ol>
</li>
<li><p><strong>Template Method Pattern</strong>  Standard transaction workflow (Validate  Debit  Credit  Notify).</p>
<ol>
<li><p><strong>Why Template?</strong></p>
<ul>
<li><p>All transactions (add money, transfer, refund) follow the same skeleton: <em>validate  debit/credit  update status  notify</em>.</p>
</li>
<li><p>Only some steps differ (refund logic vs transfer logic).</p>
</li>
</ul>
</li>
<li><p><strong>Why not Chain of Responsibility?</strong></p>
<ul>
<li>Chain is for passing requests along handlers dynamically. But our transaction flow is strict and sequential, not optional.</li>
</ul>
</li>
<li><p><strong>Why not Command Pattern?</strong></p>
<ul>
<li>Command encapsulates actions as objects (undo/redo). We need structured workflow, not undo commands.</li>
</ul>
</li>
</ol>
</li>
<li><p><strong>Factory Pattern</strong>  Create the right <code>Transaction</code> object.</p>
<ol>
<li><p><strong>Why Factory?</strong></p>
<ul>
<li><p>We need to create <code>AddMoneyTransaction</code>, <code>SendMoneyTransaction</code>, or <code>RefundTransaction</code> dynamically.</p>
</li>
<li><p>Centralized creation avoids <code>if-else</code> scattered everywhere.</p>
</li>
</ul>
</li>
<li><p><strong>Why not Builder?</strong></p>
<ul>
<li>Builder is for stepwise object construction (useful for complex objects). Our transaction objects are straightforward.</li>
</ul>
</li>
<li><p><strong>Why not Abstract Factory?</strong></p>
<ul>
<li>Abstract Factory creates <strong>families</strong> of related objects. Here, only one family exists (transactions).</li>
</ul>
</li>
</ol>
</li>
<li><p><strong>Observer Pattern</strong>  Notify users on transaction completion.</p>
<ol>
<li><p><strong>Why Observer?</strong></p>
<ul>
<li><p>After a transaction, multiple services (SMS, Email, Push) need notification.</p>
</li>
<li><p>Observer decouples transaction logic from notification system.</p>
</li>
</ul>
</li>
<li><p><strong>Why not Mediator?</strong></p>
<ul>
<li>Mediator centralizes communication between objects, but here we dont want a central coordinator, we want one-to-many updates.</li>
</ul>
</li>
<li><p><strong>Why not Publisher-Subscriber with Message Queue?</strong></p>
<ul>
<li>That would be a distributed solution. For in-process design, Observer is sufficient.</li>
</ul>
</li>
</ol>
</li>
<li><p><strong>State Pattern</strong>  Handle transaction states (<code>PENDING</code>, <code>SUCCESS</code>, etc.).</p>
<ol>
<li><p><strong>Why State?</strong></p>
<ul>
<li><p>A transaction can move from <code>PENDING  SUCCESS</code>, or <code>PENDING  FAILED</code>, etc.</p>
</li>
<li><p>Each state has different rules (e.g., SUCCESS cannot go back to PENDING).</p>
</li>
</ul>
</li>
<li><p><strong>Why not Strategy?</strong></p>
<ul>
<li>Strategy is for choosing <em>different algorithms</em>. Here, we need to model <em>object behavior change over time</em>.</li>
</ul>
</li>
<li><p><strong>Why not Enum with Switch Case?</strong></p>
<ul>
<li>Enums are fine for simple state. But extensibility suffers when adding new states or behaviors. State Pattern is more scalable.</li>
</ul>
</li>
</ol>
</li>
<li><p><strong>Singleton Pattern</strong>  TransactionManager (to avoid inconsistent transaction coordination).</p>
<ol>
<li><p><strong>Why Singleton?</strong></p>
<ul>
<li>TransactionManager should coordinate transactions globally. Multiple instances would risk inconsistent tracking.</li>
</ul>
</li>
<li><p><strong>Why not Static Class?</strong></p>
<ul>
<li>Static class prevents dependency injection/testing. Singleton provides controlled access + lazy initialization.</li>
</ul>
</li>
<li><p><strong>Why not Monostate?</strong></p>
<ul>
<li>Monostate shares state across instances, but still allows multiple objects. For a central coordinator, true Singleton is cleaner.</li>
</ul>
</li>
</ol>
</li>
</ol>
<h3 id="heading-concurrency-challenges-to-handle">🔥 Concurrency Challenges to Handle</h3>
<ul>
<li><p><strong>Race Condition:</strong> Two concurrent debits must not allow balance to go negative.</p>
</li>
<li><p><strong>Deadlock Avoidance:</strong> If two users send money to each other simultaneously, system should not deadlock.</p>
</li>
<li><p><strong>Atomicity:</strong> Debit and credit should be all-or-nothing.</p>
</li>
<li><p><strong>Thread-Safe Wallets:</strong> Ensure balance updates are synchronized correctly.</p>
</li>
</ul>
<h2 id="heading-concurrency-choices"> Concurrency Choices</h2>
<p><img src="https://kroki.io/d2/svg/eNqtVNtOwzAMfe9XWOUFHjatZePSB6ShaRLSEGiAeHYXt4sWEpRmTAjt30l62TIo4yKiSq2T2OfYPi7jmmaGK5mA5vncBC-oiwTeAgAWd2ZKZjyvTACBr2ppOiRzLikBhrkme7AO1kHwUJAeJhC6N0S9KCx9ijk-25vPpAslnW1eBTXhCqPVwlrhwUkPBxmG5W6mpLG4QumPJ6kSLAGjlzuglw1o3It_BZr1T-P0pA3UP_kMOlGzxTVKzMlddhbcaEaayxwmKuezmoWPmnEhXOTxeBhFdeQtk_M-HqdnbUx65WplAmCf6dJhVCQmamWrcDWCMdeFCZt8q2K4JqPMBdXQHrctu6xcYb27g1dtuDQ7GhlfWokMyu11U5YRGkyxcHQeUQgyMLrcU4mI4vPjtLX6Hou2nKvoVmL28lStnNjg0FWA2NEmawfZ_ZzXeuNv1VL7269f-NtMD2BEyISr-a2mF5JufGAs1KqaAuhcgCeSbt2ke42yyKwowShPrN9PxBe6_wnMdhC_n4G9Si-jO8SmzV2_DVG3ZFK2wlPfF6B9ZHRWixolf0JDvtD-xKNqZ1zzcC29I_vzYv9J5B2id3gO" alt class="image--center mx-auto" /></p>
<ol>
<li><p><strong>Fine-Grained Locking per Wallet</strong></p>
<ul>
<li><p>Avoids blocking all transactions globally.</p>
</li>
<li><p><strong>Why not Global Lock?</strong>  Poor scalability; one user blocks all.</p>
</li>
</ul>
</li>
<li><p><strong>Consistent Lock Ordering (by UserId)</strong></p>
<ul>
<li><p>Prevents deadlock when two users transfer to each other.</p>
</li>
<li><p><strong>Why not Random Locking?</strong>  Leads to deadlocks.</p>
</li>
</ul>
</li>
<li><p><strong>Optimistic Concurrency (Version Check)</strong></p>
<ul>
<li>Not chosen here because wallet balances are critical  safer with pessimistic locks.</li>
</ul>
</li>
</ol>
<h3 id="heading-algorithms-involved"> Algorithms Involved</h3>
<ol>
<li><p><strong>Concurrency Control Algorithm</strong></p>
<ul>
<li><p>Use fine-grained locks per wallet instead of global locks for scalability.</p>
</li>
<li><p>Always acquire locks in a <strong>consistent order (lower userId first)</strong> to avoid deadlocks.</p>
</li>
</ul>
</li>
<li><p><strong>Idempotency Algorithm</strong></p>
<ul>
<li><p>Maintain a <strong>transactionId  status</strong> map.</p>
</li>
<li><p>If the same request is retried, return previous result.</p>
</li>
</ul>
</li>
<li><p><strong>Rollback Algorithm</strong></p>
<ul>
<li>If debit succeeds but credit fails, perform rollback.</li>
</ul>
</li>
<li><p><strong>Mini-Statement Algorithm</strong></p>
<ul>
<li>Use a <strong>priority queue / sorted list</strong> for recent transactions.</li>
</ul>
</li>
</ol>
<h2 id="heading-code">Code</h2>
<p>Covered in our <a target="_blank" href="https://interview.lldcoding.com/dashboard/course1?chapter=%5BNEW%5D+Paytm%2FPhonePe+Wallet-L2FwaS9jb250ZW50L3BheXRtLXBob25lcGUtd2FsbGV0LmNodW5rMC5lbmNyeXB0ZWQ%3D">premium course</a></p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/PQMr65Ojq-Y">https://youtu.be/PQMr65Ojq-Y</a></div>
]]></description><link>https://lldcoding.com/design-lld-paytmphone-wallet-system-machine-coding</link><guid isPermaLink="true">https://lldcoding.com/design-lld-paytmphone-wallet-system-machine-coding</guid><category><![CDATA[Programming Blogs]]></category><category><![CDATA[Java]]></category><category><![CDATA[interview]]></category><category><![CDATA[LLD]]></category><category><![CDATA[interview questions]]></category><category><![CDATA[C++]]></category><dc:creator><![CDATA[Subhahu Jain]]></dc:creator></item><item><title><![CDATA[🚚 Delivery Truck Loading System Concurrency Problem]]></title><description><![CDATA[<h2 id="heading-problem-setup">📝 Problem Setup</h2>
<p>A logistics company has multiple <strong>loading docks</strong> where workers load packages into delivery trucks.</p>
<ul>
<li><p>Each truck has a <strong>weight/volume limit</strong>.</p>
</li>
<li><p>Packages arrive continuously from the warehouse.</p>
</li>
<li><p>Multiple workers can attempt to load packages <strong>in parallel</strong>.</p>
</li>
<li><p>Once a truck is full, it should be dispatched immediately, and a new empty truck should arrive at the dock.</p>
</li>
</ul>
<h3 id="heading-concurrency-challenge"> Concurrency Challenge</h3>
<p><strong>Naive approach</strong>:<br />Each worker checks whether the truck has space left and then puts the package in.</p>
<p><strong>Problems</strong></p>
<ul>
<li><p>Two workers check simultaneously  both see space available.</p>
</li>
<li><p>Both load packages  truck exceeds capacity.</p>
</li>
<li><p>Or, one worker sees truck is full, but another worker just dispatched it  confusion: packages might get lost or assigned incorrectly.</p>
</li>
</ul>
<h3 id="heading-solution-approaches"><strong>🔑 Solution Approaches</strong></h3>
<h3 id="heading-1-naive-locking">1. <strong>Naive Locking</strong></h3>
<ul>
<li><p>Place a <code>synchronized</code> lock on the truck while loading.</p>
</li>
<li><p>Multiple workers try to load packages onto a docks current truck.</p>
<ul>
<li><p><strong>Correctness first</strong>: never overfill a truck; never dispatch twice; never lose a package.</p>
<ul>
<li>Only one worker can load at a time.</li>
</ul>
</li>
</ul>
</li>
<li><p>Well <strong>serialize</strong> critical operations with a <strong>single lock</strong> so only one worker mutates truck state at a time.</p>
</li>
</ul>
<p>🔒 Locking plan (coarse-grained / monitor)</p>
<ul>
<li><p>Use <strong>one monitor lock per dock</strong> (i.e., <code>synchronized</code> on the <code>Dock</code> instance).</p>
<ul>
<li><p>Why lock the <strong>dock</strong> (not the truck)?</p>
<ul>
<li>We will discuss this in our <a target="_blank" href="https://interview.lldcoding.com/">course</a>.</li>
</ul>
</li>
</ul>
</li>
<li><p>Every operation that reads + writes <strong>truck capacity/used/state</strong> runs <strong>inside the same lock</strong>.</p>
</li>
<li><p>The whole sequence <strong>check  load  maybe dispatch  maybe replace</strong> is atomic w.r.t. other workers.</p>
</li>
</ul>
<p><strong>Code</strong></p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> java.util.*;
<span class="hljs-keyword">import</span> java.util.concurrent.*;
<span class="hljs-keyword">import</span> java.util.concurrent.atomic.AtomicInteger;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">NaiveDockLoading</span> </span>{

    <span class="hljs-comment">// Simple package with a weight</span>
    <span class="hljs-keyword">static</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Package</span> </span>{
        <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> id;
        <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> weight;
        Package(<span class="hljs-keyword">int</span> id, <span class="hljs-keyword">int</span> weight) { <span class="hljs-keyword">this</span>.id = id; <span class="hljs-keyword">this</span>.weight = weight; }
        <span class="hljs-meta">@Override</span> <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">toString</span><span class="hljs-params">()</span> </span>{ <span class="hljs-keyword">return</span> <span class="hljs-string">"Pkg#"</span> + id + <span class="hljs-string">"("</span> + weight + <span class="hljs-string">")"</span>; }
    }

    <span class="hljs-class"><span class="hljs-keyword">enum</span> <span class="hljs-title">TruckState</span> </span>{ EMPTY, LOADING, FULL, DISPATCHED }

    <span class="hljs-keyword">static</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Truck</span> </span>{
        <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> id;
        <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> capacity;
        <span class="hljs-keyword">int</span> used = <span class="hljs-number">0</span>;
        TruckState state = TruckState.EMPTY;
        <span class="hljs-keyword">final</span> List&lt;Package&gt; loaded = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();

        Truck(<span class="hljs-keyword">int</span> id, <span class="hljs-keyword">int</span> capacity) {
            <span class="hljs-keyword">this</span>.id = id;
            <span class="hljs-keyword">this</span>.capacity = capacity;
        }
    }

    <span class="hljs-keyword">static</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Dock</span> </span>{
        <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> truckCapacity;
        <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> AtomicInteger truckSeq = <span class="hljs-keyword">new</span> AtomicInteger(<span class="hljs-number">1</span>);
        <span class="hljs-keyword">private</span> Truck currentTruck;

        <span class="hljs-comment">// One coarse-grained lock: the Dock object itself</span>
        Dock(<span class="hljs-keyword">int</span> truckCapacity) {
            <span class="hljs-keyword">this</span>.truckCapacity = truckCapacity;
            <span class="hljs-keyword">this</span>.currentTruck = <span class="hljs-keyword">new</span> Truck(truckSeq.getAndIncrement(), truckCapacity);
        }

        <span class="hljs-comment">// Called by many worker threads</span>
        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">load</span><span class="hljs-params">(Package pkg)</span> </span>{
            <span class="hljs-keyword">synchronized</span> (<span class="hljs-keyword">this</span>) {
                ensureActiveTruck();

                <span class="hljs-comment">// If it doesn't fit, dispatch and replace, then load on the new truck.</span>
                <span class="hljs-keyword">if</span> (!fits(pkg, currentTruck)) {
                    dispatchLocked(currentTruck);
                    currentTruck = <span class="hljs-keyword">new</span> Truck(truckSeq.getAndIncrement(), truckCapacity);
                }

                <span class="hljs-comment">// Now it must fit</span>
                placeLocked(pkg, currentTruck);

                <span class="hljs-comment">// If truck just became full, dispatch and replace</span>
                <span class="hljs-keyword">if</span> (currentTruck.used == currentTruck.capacity) {
                    currentTruck.state = TruckState.FULL;
                    dispatchLocked(currentTruck);
                    currentTruck = <span class="hljs-keyword">new</span> Truck(truckSeq.getAndIncrement(), truckCapacity);
                }
            } <span class="hljs-comment">// lock released</span>
        }

        <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">ensureActiveTruck</span><span class="hljs-params">()</span> </span>{
            <span class="hljs-keyword">if</span> (currentTruck.state == TruckState.DISPATCHED) {
                currentTruck = <span class="hljs-keyword">new</span> Truck(truckSeq.getAndIncrement(), truckCapacity);
            }
        }

        <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">fits</span><span class="hljs-params">(Package p, Truck t)</span> </span>{
            <span class="hljs-keyword">return</span> t.used + p.weight &lt;= t.capacity &amp;&amp; t.state != TruckState.DISPATCHED;
        }

        <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">placeLocked</span><span class="hljs-params">(Package p, Truck t)</span> </span>{
            <span class="hljs-comment">// Inside dock lock: check+update is atomic</span>
            <span class="hljs-keyword">if</span> (t.state == TruckState.DISPATCHED) {
                <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> IllegalStateException(<span class="hljs-string">"Cannot load on dispatched truck "</span> + t.id);
            }
            <span class="hljs-keyword">if</span> (t.used + p.weight &gt; t.capacity) {
                <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> IllegalStateException(<span class="hljs-string">"Overfill prevented for truck "</span> + t.id);
            }
            <span class="hljs-keyword">if</span> (t.used == <span class="hljs-number">0</span>) t.state = TruckState.LOADING;
            t.loaded.add(p);
            t.used += p.weight;
            System.out.printf(<span class="hljs-string">"[DOCK] Loaded %s on truck #%d (used=%d/%d)%n"</span>,
                    p, t.id, t.used, t.capacity);
        }

        <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">dispatchLocked</span><span class="hljs-params">(Truck t)</span> </span>{
            <span class="hljs-keyword">if</span> (t.state == TruckState.DISPATCHED) <span class="hljs-keyword">return</span>; <span class="hljs-comment">// idempotent</span>
            t.state = TruckState.DISPATCHED;
            System.out.printf(<span class="hljs-string">"[DISPATCH] Truck #%d dispatched with %d/%d (packages=%d)%n"</span>,
                    t.id, t.used, t.capacity, t.loaded.size());
            <span class="hljs-comment">// In naive solution: pretend to hand off to transport subsystem here.</span>
            <span class="hljs-comment">// Avoid I/O here to keep critical section small (still naive, but less awful).</span>
        }
    }

    <span class="hljs-comment">// Demo harness: many workers calling Dock.load(...)</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> <span class="hljs-keyword">throws</span> InterruptedException </span>{
        Dock dock = <span class="hljs-keyword">new</span> Dock(<span class="hljs-comment">/*truckCapacity*/</span> <span class="hljs-number">100</span>);

        <span class="hljs-comment">// Create a pool of workers; they all contend on the same dock lock.</span>
        ExecutorService workers = Executors.newFixedThreadPool(<span class="hljs-number">8</span>);

        <span class="hljs-comment">// Generate random packages totaling more than a few trucks</span>
        List&lt;Package&gt; incoming = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();
        Random r = <span class="hljs-keyword">new</span> Random(<span class="hljs-number">42</span>);
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">1</span>; i &lt;= <span class="hljs-number">60</span>; i++) {
            <span class="hljs-keyword">int</span> w = <span class="hljs-number">5</span> + r.nextInt(<span class="hljs-number">30</span>); <span class="hljs-comment">// 5..34</span>
            incoming.add(<span class="hljs-keyword">new</span> Package(i, w));
        }

        <span class="hljs-keyword">for</span> (Package p : incoming) {
            workers.submit(() -&gt; dock.load(p));
        }

        workers.shutdown();
        workers.awaitTermination(<span class="hljs-number">1</span>, TimeUnit.MINUTES);
        System.out.println(<span class="hljs-string">"Done."</span>);
    }
}
</code></pre>
<h3 id="heading-performance-amp-limits-what-breaks-first"> Performance &amp; limits (what breaks first)</h3>
<ul>
<li><p>All workers queue behind the dock lock; CPU underutilization grows as worker count rises.</p>
</li>
<li><p>Even if you wanted to prepare a new truck in parallel, the single lock blocks it.</p>
</li>
<li><p>Javas intrinsic locks are <strong>not fair</strong>; a thread might repeatedly win the lock (lock hogging), causing <strong>starvation</strong> under load spikes.</p>
</li>
<li><p>If package arrival rate &gt; service rate, the <strong>work queue grows unbounded</strong> (in this naive example, we submit tasks freely).</p>
</li>
</ul>
<p>More Better Solutions Approaches and Fix for above problems will be covered in our <a target="_blank" href="https://interview.lldcoding.com/">course</a>.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/PG7MUTlWl-U">https://youtu.be/PG7MUTlWl-U</a></div>
]]></description><link>https://lldcoding.com/delivery-truck-loading-system-concurrency-problem</link><guid isPermaLink="true">https://lldcoding.com/delivery-truck-loading-system-concurrency-problem</guid><category><![CDATA[General Programming]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[interview]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Java]]></category><category><![CDATA[C#]]></category><category><![CDATA[C++]]></category><dc:creator><![CDATA[Subhahu Jain]]></dc:creator></item><item><title><![CDATA[🧩 Jigsaw Puzzle Builder (Parallel Parts) Concurrency Problem]]></title><description><![CDATA[<h2 id="heading-the-problem"><strong>🧩 The Problem</strong></h2>
<p>Were building a <strong>digital jigsaw puzzle game</strong> (or simulation) where:</p>
<ul>
<li><p>The puzzle has <strong>many pieces</strong> (hundreds or thousands).</p>
</li>
<li><p>Each piece can be placed independently <strong>unless it connects to another</strong>.</p>
</li>
<li><p>We want to <strong>speed up</strong> building the puzzle by letting multiple workers (threads) place pieces at the same time.</p>
</li>
</ul>
<h3 id="heading-solution-approaches">Solution Approaches</h3>
<h3 id="heading-1-step-1-the-naive-single-threaded-approach">1 Step 1  The Naive Single-Threaded Approach</h3>
<p>Imagine we have a <strong>jigsaw puzzle</strong> with 1,000 pieces.<br />We write a simple loop:</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PuzzleBuilder</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> piece = <span class="hljs-number">1</span>; piece &lt;= <span class="hljs-number">1000</span>; piece++) {
            placePiece(piece);
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">placePiece</span><span class="hljs-params">(<span class="hljs-keyword">int</span> id)</span> </span>{
        System.out.println(<span class="hljs-string">"Placed piece "</span> + id);
        <span class="hljs-keyword">try</span> { Thread.sleep(<span class="hljs-number">10</span>); } <span class="hljs-keyword">catch</span> (InterruptedException e) {}
    }
}
</code></pre>
<p>📝 <strong>Idea:</strong> One person places all pieces <strong>in order</strong>.<br /> Works fine for small puzzles.<br /> But slow for large puzzles  only <strong>one worker</strong> is active.</p>
<p><strong>The Real-World Problem</strong></p>
<p>In real life:</p>
<ul>
<li><p>Multiple people can work on <strong>different parts</strong> of the puzzle at the same time.</p>
</li>
<li><p>We <strong>dont need to place pieces in strict numeric order</strong>  only in correct <strong>locations</strong>.</p>
</li>
<li><p>Our single-thread version wastes potential <strong>parallelism</strong>.</p>
</li>
</ul>
<h2 id="heading-more-solutions">More Solutions</h2>
<p>will be discussed in our <a target="_blank" href="https://interview.lldcoding.com/dashboard?chapter=%5BNEW%5D+%F0%9F%A7%A9+Jigsaw+Puzzle+Builder+Concurrency+Problem-L2FwaS9jb250ZW50L0ppZ3Nhdy1QdXp6bGUtQnVpbGRlci1Db25jdXJyZW5jeS1Qcm9ibGVtLmNodW5rMC5lbmNyeXB0ZWQ%3D">course</a>.</p>
]]></description><link>https://lldcoding.com/jigsaw-puzzle-builder-parallel-parts-concurrency-problem</link><guid isPermaLink="true">https://lldcoding.com/jigsaw-puzzle-builder-parallel-parts-concurrency-problem</guid><category><![CDATA[Programming Blogs]]></category><category><![CDATA[General Programming]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Java]]></category><dc:creator><![CDATA[Subhahu Jain]]></dc:creator></item><item><title><![CDATA[📦 Warehouse Packing Simulation Concurrency Problem]]></title><description><![CDATA[<p>Let's model a warehouse system where multiple workers pack orders concurrently while managing shared resources.</p>
<h2 id="heading-problem-statement"><strong>Problem Statement</strong></h2>
<ul>
<li><p>Multiple packing stations process orders simultaneously</p>
</li>
<li><p>Shared inventory with limited stock</p>
</li>
<li><p>Orders may require multiple items</p>
</li>
<li><p>Prevent race conditions during inventory access</p>
</li>
<li><p>Handle backorders when stock is insufficient</p>
</li>
</ul>
<h2 id="heading-solution-approaches">Solution Approaches</h2>
<h3 id="heading-basic-solution"><strong>Basic Solution</strong></h3>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Warehouse</span> </span>{
    <span class="hljs-keyword">private</span> Map&lt;String, Integer&gt; inventory = <span class="hljs-keyword">new</span> HashMap&lt;&gt;();

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">pickItem</span><span class="hljs-params">(String sku, <span class="hljs-keyword">int</span> quantity)</span> </span>{
        <span class="hljs-keyword">if</span> (inventory.getOrDefault(sku, <span class="hljs-number">0</span>) &gt;= quantity) {
            inventory.put(sku, inventory.get(sku) - quantity);
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;
        }
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">restock</span><span class="hljs-params">(String sku, <span class="hljs-keyword">int</span> quantity)</span> </span>{
        inventory.put(sku, inventory.getOrDefault(sku, <span class="hljs-number">0</span>) + quantity);
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PackingStation</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">processOrder</span><span class="hljs-params">(Order order, Warehouse warehouse)</span> </span>{
        <span class="hljs-keyword">for</span> (Map.Entry&lt;String, Integer&gt; item : order.getItems().entrySet()) {
            <span class="hljs-keyword">if</span> (!warehouse.pickItem(item.getKey(), item.getValue())) {
                order.backorder();
                <span class="hljs-keyword">return</span>;
            }
        }
        order.pack();
    }
}
</code></pre>
<h3 id="heading-problems"><strong>Problems</strong></h3>
<ol>
<li><p><strong>Race Condition</strong>: Two threads can oversell stock</p>
<p> <a target="_blank" href="https://mermaid.live/edit#pako:eNqVkW1LwzAQx79KuFcO2pE23bIFOvABQURf-IAgfROXW1toky1NhnPsu5tOJ1NB8F7dHfe7_z1sYW4UgoAOVx71HC9qWVrZFpoEe6gsSkVO49nsSq9RO2M3gtyFXEfurx_jhCbkZOU2-WjwDTj7L_BD4cnWDo-IUczy9E-J30SWJ5_ErXFIzBotOQIuay0b0o8SqrvK-EaRFyRxOoAISlsrEM56jKBF28o-hG3frgBXYYsFiOAqXEjfuAIKvQvYUupnY9oDaY0vKxAL2XQh8ksl3eG8X1mLWqE9N147EAnf9wCxhVcQKaPDKU8mY5ZMU5pRNo5gA4Jlw4zxEaWcMTphnO8ieNur0uGEZ9NjiwBVHfa9-fjx_tW7d6ApmBc"><img src="https://mermaid.ink/img/pako:eNqVkW1LwzAQx79KuFcO2pE23bIFOvABQURf-IAgfROXW1toky1NhnPsu5tOJ1NB8F7dHfe7_z1sYW4UgoAOVx71HC9qWVrZFpoEe6gsSkVO49nsSq9RO2M3gtyFXEfurx_jhCbkZOU2-WjwDTj7L_BD4cnWDo-IUczy9E-J30SWJ5_ErXFIzBotOQIuay0b0o8SqrvK-EaRFyRxOoAISlsrEM56jKBF28o-hG3frgBXYYsFiOAqXEjfuAIKvQvYUupnY9oDaY0vKxAL2XQh8ksl3eG8X1mLWqE9N147EAnf9wCxhVcQKaPDKU8mY5ZMU5pRNo5gA4Jlw4zxEaWcMTphnO8ieNur0uGEZ9NjiwBVHfa9-fjx_tW7d6ApmBc?type=png" alt /></a></p>
</li>
<li><p><strong>Dirty Reads</strong>: Temporary negative inventory possible</p>
</li>
<li><p><strong>Lost Updates</strong>: Restocks might get overwritten</p>
</li>
</ol>
<h2 id="heading-fix-for-above-mentioned-problem-coarse-grained-synchronization"><strong>Fix for Above mentioned problem: Coarse-Grained Synchronization</strong></h2>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Warehouse</span> </span>{
    <span class="hljs-keyword">private</span> Map&lt;String, Integer&gt; inventory = <span class="hljs-keyword">new</span> HashMap&lt;&gt;();

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">synchronized</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">pickItem</span><span class="hljs-params">(String sku, <span class="hljs-keyword">int</span> quantity)</span> </span>{
        <span class="hljs-keyword">if</span> (inventory.getOrDefault(sku, <span class="hljs-number">0</span>) &gt;= quantity) {
            inventory.put(sku, inventory.get(sku) - quantity);
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;
        }
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">synchronized</span> <span class="hljs-keyword">void</span> <span class="hljs-title">restock</span><span class="hljs-params">(String sku, <span class="hljs-keyword">int</span> quantity)</span> </span>{
        inventory.put(sku, inventory.getOrDefault(sku, <span class="hljs-number">0</span>) + quantity);
    }
}
</code></pre>
<ol>
<li><p>Solves race conditions with method-level <code>synchronized</code></p>
</li>
<li><p>Ensures atomic inventory updates</p>
</li>
</ol>
<h3 id="heading-new-problems"><strong>New Problems</strong></h3>
<p><strong>Throughput Bottleneck</strong>:</p>
<ul>
<li><p>Entire warehouse locks during each operation</p>
</li>
<li><p>Packing station working with SKU-A blocks SKU-B access</p>
<p>  <a target="_blank" href="https://mermaid.live/edit#pako:eNpdkMtugzAQRX_FmjUgG5NAvKjUJLu2UqW0qtSShQUOWAEbGVtqS_j3GhBZdFZzZ3TPPAYodCmAQWV4V6O3Y66Qj8evk-VWakUYepXFVaoKnZ7eQ4LJGYXhw-1ZF9cefXAjau16cUP71REzX5bWO84L67B26H9WvLD2zQTzCAj8GrIEZo0TAbTCtHySMEykHGwtWpED82kpLtw1Nodcjd7WcfWpdbs6jXZVDezCm94r15XciqPk_sb2XjVClcIctFMWWExmBrABvr2iONqlJNtSsotxguk2gB9gNIkSmm4wTinFGU3TMYDfeSqOsnQTgCil1eZleej81_EPuYJtpw"><img src="https://mermaid.ink/img/pako:eNpdkMtugzAQRX_FmjUgG5NAvKjUJLu2UqW0qtSShQUOWAEbGVtqS_j3GhBZdFZzZ3TPPAYodCmAQWV4V6O3Y66Qj8evk-VWakUYepXFVaoKnZ7eQ4LJGYXhw-1ZF9cefXAjau16cUP71REzX5bWO84L67B26H9WvLD2zQTzCAj8GrIEZo0TAbTCtHySMEykHGwtWpED82kpLtw1Nodcjd7WcfWpdbs6jXZVDezCm94r15XciqPk_sb2XjVClcIctFMWWExmBrABvr2iONqlJNtSsotxguk2gB9gNIkSmm4wTinFGU3TMYDfeSqOsnQTgCil1eZleej81_EPuYJtpw?type=png" alt /></a></p>
</li>
</ul>
<p><strong>Deadlock Risk</strong>:</p>
<pre><code class="lang-java"><span class="hljs-comment">// Thread 1</span>
<span class="hljs-function"><span class="hljs-keyword">synchronized</span> <span class="hljs-keyword">void</span> <span class="hljs-title">processOrder</span><span class="hljs-params">()</span> </span>{
    pickItem(<span class="hljs-string">"A"</span>, <span class="hljs-number">1</span>);
    pickItem(<span class="hljs-string">"B"</span>, <span class="hljs-number">1</span>); <span class="hljs-comment">// Deadlock if Thread 2 holds B and wants A</span>
}
</code></pre>
<p>Fix and other solution will be covered in our <a target="_blank" href="https://interview.lldcoding.com/dashboard?chapter=%5BNEW%5D+%F0%9F%93%A6+Warehouse+Packing+Simulation+Concurrency+Problem-L2FwaS9jb250ZW50L1dhcmVob3VzZS1QYWNraW5nLVNpbXVsYXRpb24tQ29uY3VycmVuY3ktUHJvYmxlbS5jaHVuazAuZW5jcnlwdGVk">course</a>.</p>
]]></description><link>https://lldcoding.com/warehouse-packing-simulation-concurrency-problem</link><guid isPermaLink="true">https://lldcoding.com/warehouse-packing-simulation-concurrency-problem</guid><category><![CDATA[General Programming]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Java]]></category><dc:creator><![CDATA[Subhahu Jain]]></dc:creator></item><item><title><![CDATA[🎮 Online Matchmaking (Real-Time Queue Handling) Concurrency Problem]]></title><description><![CDATA[<h2 id="heading-problem">Problem</h2>
<p>Simulate an <strong>online matchmaking system</strong> where:</p>
<ul>
<li><p>Players join a matchmaking queue in real-time.</p>
</li>
<li><p>When <strong>enough players</strong> are available (say, 4 or 10), a <strong>match is created</strong>.</p>
</li>
<li><p>Players are then <strong>removed from the queue</strong>, and a <strong>game session</strong> is started.</p>
</li>
</ul>
<h2 id="heading-solution-approaches">Solution Approaches</h2>
<h3 id="heading-naive-basic-implementation">Naive / Basic Implementation</h3>
<p>we just keep a <strong>normal list</strong> of players waiting for a match.</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> java.util.*;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">NaiveMatchmaking</span> </span>{
    <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> PLAYERS_PER_MATCH = <span class="hljs-number">4</span>;
    <span class="hljs-keyword">static</span> List&lt;Integer&gt; waitingPlayers = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-comment">// Players joining (simulated)</span>
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">1</span>; i &lt;= <span class="hljs-number">8</span>; i++) {
            joinQueue(i);
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">joinQueue</span><span class="hljs-params">(<span class="hljs-keyword">int</span> playerId)</span> </span>{
        waitingPlayers.add(playerId);
        System.out.println(<span class="hljs-string">"🙋 Player #"</span> + playerId + <span class="hljs-string">" joined queue."</span>);

        <span class="hljs-keyword">if</span> (waitingPlayers.size() &gt;= PLAYERS_PER_MATCH) {
            startMatch();
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">startMatch</span><span class="hljs-params">()</span> </span>{
        List&lt;Integer&gt; matchPlayers = waitingPlayers.subList(<span class="hljs-number">0</span>, PLAYERS_PER_MATCH);
        System.out.println(<span class="hljs-string">"🎮 Match started: "</span> + matchPlayers);
        matchPlayers.clear(); <span class="hljs-comment">// remove them from queue</span>
    }
}
</code></pre>
<p><a target="_blank" href="https://mermaid.live/edit#pako:eNqNkk1PwzAMhv9K5FMnlalbunXLYRe4IDEkTkioF9N4XaBNSpogxrT_TmgZQxtfPUSx87yvndRbKIwkENDSkydd0IXC0mKdaxa-Bq1ThWpQO7ZEpU-z16ieaYmuWNf4qHR5Stx48sSwZbeoXCD6RM_167vz2WJxbCVYHQ6iQQ9VxjRsZSxrKtyQbdmIOcNm_eGvLg9G6a5m1Esv5eCgOsaDQ8cKhlJ-J8BqfyVLWKypZem-pQP0g_Npb60LL9VlosGf8o_GWn9_pVoXJXH6b01REdqvJUjLPggbiKG0SoJw1lMMNdnw8CGE7TuSg1tTTTmIsJW0Ql-5HHK9C7Lwg--MqfdKa3y5BrHCqg2RbyS6_Tx9IqEe2XPjtQMx4p0FiC28gBjzZDjPRrMpH83HSZrwaQwbEDwdpjybJEnGeTLjWbaL4bUrmgxn2SQGksoZu-zHuJvm3RsBp-Yr"><img src="https://mermaid.ink/img/pako:eNqNkk1PwzAMhv9K5FMnlalbunXLYRe4IDEkTkioF9N4XaBNSpogxrT_TmgZQxtfPUSx87yvndRbKIwkENDSkydd0IXC0mKdaxa-Bq1ThWpQO7ZEpU-z16ieaYmuWNf4qHR5Stx48sSwZbeoXCD6RM_167vz2WJxbCVYHQ6iQQ9VxjRsZSxrKtyQbdmIOcNm_eGvLg9G6a5m1Esv5eCgOsaDQ8cKhlJ-J8BqfyVLWKypZem-pQP0g_Npb60LL9VlosGf8o_GWn9_pVoXJXH6b01REdqvJUjLPggbiKG0SoJw1lMMNdnw8CGE7TuSg1tTTTmIsJW0Ql-5HHK9C7Lwg--MqfdKa3y5BrHCqg2RbyS6_Tx9IqEe2XPjtQMx4p0FiC28gBjzZDjPRrMpH83HSZrwaQwbEDwdpjybJEnGeTLjWbaL4bUrmgxn2SQGksoZu-zHuJvm3RsBp-Yr?type=png" alt /></a></p>
<p><strong>Problem  Concurrency Breaks This</strong></p>
<p>Now, in <strong>real life</strong>:</p>
<ul>
<li><p>Players <strong>join in parallel</strong> (multiple threads)</p>
</li>
<li><p>Matches are formed in <strong>real-time</strong></p>
</li>
<li><p>The list <code>waitingPlayers</code> is <strong>not thread-safe</strong>  <strong>Race conditions happen</strong>:</p>
<ul>
<li><p><strong>Two threads</strong> may see enough players and <strong>start the same match twice</strong>.</p>
</li>
<li><p>Players may be <strong>skipped</strong> or <strong>duplicated</strong>.</p>
</li>
<li><p>Modifying the same list from multiple threads  <code>ConcurrentModificationException</code>.</p>
</li>
</ul>
</li>
</ul>
<p>Example failure scenario:</p>
<blockquote>
<p>Thread 1: sees 4 players  starting match...<br />Thread 2: sees same 4 players  starting another match...</p>
</blockquote>
<h3 id="heading-first-fix-add-locks-synchronized"><strong> First Fix  Add Locks (</strong><code>synchronized</code><strong>)</strong></h3>
<p>try to fix it by synchronizing the join method.</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">synchronized</span> <span class="hljs-keyword">void</span> <span class="hljs-title">joinQueue</span><span class="hljs-params">(<span class="hljs-keyword">int</span> playerId)</span> </span>{
    waitingPlayers.add(playerId);
    <span class="hljs-keyword">if</span> (waitingPlayers.size() &gt;= PLAYERS_PER_MATCH) {
        startMatch();
    }
}

<span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">synchronized</span> <span class="hljs-keyword">void</span> <span class="hljs-title">startMatch</span><span class="hljs-params">()</span> </span>{
    List&lt;Integer&gt; matchPlayers = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;(waitingPlayers.subList(<span class="hljs-number">0</span>, PLAYERS_PER_MATCH));
    System.out.println(<span class="hljs-string">"🎮 Match started: "</span> + matchPlayers);
    waitingPlayers.removeAll(matchPlayers);
}
</code></pre>
<p> <strong>This works</strong> for correctness.<br /> <strong>But</strong>:</p>
<ul>
<li><p>It <strong>blocks all player joins</strong> when one player is joining or a match is starting  <strong>slower</strong>.</p>
</li>
<li><p>If you scale to thousands of players, this becomes a <strong>bottleneck</strong>.</p>
</li>
</ul>
<h2 id="heading-better-approach">Better Approach</h2>
<p>will be covered in our <a target="_blank" href="https://interview.lldcoding.com/dashboard?chapter=%5BNEW%5D+%F0%9F%8E%AE+Online+Matchmaking+Queue+Concurrency+Problem-L2FwaS9jb250ZW50L09ubGluZS1NYXRjaG1ha2luZy1RdWV1ZS1Db25jdXJyZW5jeS1Qcm9ibGVtLmNodW5rMC5lbmNyeXB0ZWQ%3D">course</a>.</p>
]]></description><link>https://lldcoding.com/online-matchmaking-real-time-queue-handling-concurrency-problem</link><guid isPermaLink="true">https://lldcoding.com/online-matchmaking-real-time-queue-handling-concurrency-problem</guid><category><![CDATA[interview]]></category><category><![CDATA[concurrency]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Java]]></category><dc:creator><![CDATA[Subhahu Jain]]></dc:creator></item><item><title><![CDATA[📞 Call Center Queue Concurrency Problem]]></title><description><![CDATA[<h3 id="heading-objective">🎯 Objective:</h3>
<p>Simulate a <strong>call center</strong> where:</p>
<ul>
<li><p>There are a <strong>limited number of agents</strong> (say 3).</p>
</li>
<li><p>Many customers (calls) are coming in <strong>at the same time</strong>.</p>
</li>
<li><p>If all agents are busy, new calls must <strong>wait in a queue</strong> until an agent becomes free.</p>
</li>
</ul>
<blockquote>
<p>Only available agents can take calls.<br />The system should <strong>not lose any calls</strong> and must <strong>not assign 2 agents to the same call</strong>.</p>
</blockquote>
<h2 id="heading-solution-approaches"><strong>Solution Approaches</strong></h2>
<p><strong>Basic Thread Pool Approach (Fixed Agents)</strong></p>
<ol>
<li><p>We'll use a fixed thread pool where:</p>
<ul>
<li><p>Each thread represents an <strong>agent</strong></p>
</li>
<li><p>Incoming calls are <strong>tasks</strong> submitted to the executor</p>
</li>
<li><p>The executor automatically handles <strong>queuing</strong> when all agents are busy</p>
</li>
</ul>
</li>
</ol>
<pre><code class="lang-java">    <span class="hljs-keyword">import</span> java.util.concurrent.*;

    <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BasicCallCenter</span> </span>{
        <span class="hljs-comment">// 1. Configuration</span>
        <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> AGENT_COUNT = <span class="hljs-number">3</span>; 
        <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> ExecutorService agents = Executors.newFixedThreadPool(AGENT_COUNT);

        <span class="hljs-comment">// 2. Call Task Representation</span>
        <span class="hljs-keyword">static</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Call</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Runnable</span> </span>{
            <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> callId;

            <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Call</span><span class="hljs-params">(<span class="hljs-keyword">int</span> id)</span> </span>{ 
                <span class="hljs-keyword">this</span>.callId = id; 
            }

            <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">run</span><span class="hljs-params">()</span> </span>{
                <span class="hljs-comment">// 3. Call Handling Logic</span>
                System.out.println(<span class="hljs-string">"📞 Call "</span> + callId + <span class="hljs-string">" started by "</span> + 
                                  Thread.currentThread().getName());

                <span class="hljs-keyword">try</span> {
                    <span class="hljs-comment">// Simulate variable call duration (2-7 seconds)</span>
                    Thread.sleep(<span class="hljs-number">2000</span> + (<span class="hljs-keyword">long</span>)(Math.random() * <span class="hljs-number">5000</span>)); 
                } <span class="hljs-keyword">catch</span> (InterruptedException e) {
                    System.out.println(<span class="hljs-string">" Call "</span> + callId + <span class="hljs-string">" interrupted"</span>);
                }

                System.out.println(<span class="hljs-string">" Call "</span> + callId + <span class="hljs-string">" completed"</span>);
            }
        }

        <span class="hljs-comment">// 4. Simulation Driver</span>
        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
            <span class="hljs-comment">// Simulate 10 incoming calls</span>
            <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">1</span>; i &lt;= <span class="hljs-number">10</span>; i++) {
                agents.execute(<span class="hljs-keyword">new</span> Call(i)); <span class="hljs-comment">// 5. Dispatch calls</span>
                System.out.println(<span class="hljs-string">"🔔 Received call #"</span> + i);

                <span class="hljs-comment">// Random delay between calls (0-1s)</span>
                <span class="hljs-keyword">try</span> { Thread.sleep((<span class="hljs-keyword">long</span>)(Math.random() * <span class="hljs-number">1000</span>)); 
                } <span class="hljs-keyword">catch</span> (InterruptedException e) {}
            }

            <span class="hljs-comment">// 6. Clean shutdown</span>
            agents.shutdown();
        }
    }
</code></pre>
<p>    <a target="_blank" href="https://mermaid.live/edit#pako:eNqNksFqwzAMhl8l6LRBGpw4bVIfCqXbcYddRy4mVtNAYneODd1K332uTTZCF4gPxvr165ONdYVaCQQGA35alDW-tLzRvK9k5NaZa9PW7ZlLEx1416F-1F8vWFuj_snsG5QmndGzGZ0GPeyh52q3G5uwCP0Jn-6p9DnYxqwzhp4s2g9D20gPSBexshlWNmFli1h0hkUnLLqIlT-y_ozvFi16Qh5c4cqricnfOxJK4pIX5hBDo1sBzGiLMfSoe34P4Xovr8CcsMcKmDsKPHLbmQoqeXNl7hM_lOrHSq1scwJ25N3gInsW3IzT9atqlAL1QVlpgGWpZwC7wsVFlCTbIi03NN1mJCd0E8MXMJonOS3WhBSUkpIWxS2Gb9-VJGWxjgFF6x73FqbaD_ftB-N27_A"><img src="https://mermaid.ink/img/pako:eNqNksFqwzAMhl8l6LRBGpw4bVIfCqXbcYddRy4mVtNAYneODd1K332uTTZCF4gPxvr165ONdYVaCQQGA35alDW-tLzRvK9k5NaZa9PW7ZlLEx1416F-1F8vWFuj_snsG5QmndGzGZ0GPeyh52q3G5uwCP0Jn-6p9DnYxqwzhp4s2g9D20gPSBexshlWNmFli1h0hkUnLLqIlT-y_ozvFi16Qh5c4cqricnfOxJK4pIX5hBDo1sBzGiLMfSoe34P4Xovr8CcsMcKmDsKPHLbmQoqeXNl7hM_lOrHSq1scwJ25N3gInsW3IzT9atqlAL1QVlpgGWpZwC7wsVFlCTbIi03NN1mJCd0E8MXMJonOS3WhBSUkpIWxS2Gb9-VJGWxjgFF6x73FqbaD_ftB-N27_A?type=png" alt /></a></p>
<h3 id="heading-non-working-test-cases"><strong> Non-Working Test Cases</strong></h3>
<h3 id="heading-1-sustained-overload-memory-crash"><strong>1. Sustained Overload (Memory Crash)</strong></h3>
<p>    Continuous call flood.</p>
<p>    10,000 calls with 3 agents</p>
<pre><code class="lang-java">    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">1</span>; i &lt;= <span class="hljs-number">10_000</span>; i++) {
        agents.execute(<span class="hljs-keyword">new</span> Call(i));
    }
</code></pre>
<blockquote>
<p>OutOfMemoryError: Unable to create new native thread</p>
</blockquote>
<p>    Unbounded queue grows indefinitely, consuming all memory.</p>
<h3 id="heading-2-call-rejection-needed"><strong>2. Call Rejection Needed</strong></h3>
<p>Queue at capacity (business requirement), Attempt to queue 6th call when max capacity is 5<br />Silently accepts all calls<br />Should reject calls when overloaded<br /><strong>Solution</strong>: Use <code>ThreadPoolExecutor</code> with bounded queue:</p>
<pre><code class="lang-java">ExecutorService agents = <span class="hljs-keyword">new</span> ThreadPoolExecutor(
    <span class="hljs-number">3</span>, <span class="hljs-number">3</span>, <span class="hljs-number">0L</span>, TimeUnit.MILLISECONDS,
    <span class="hljs-keyword">new</span> ArrayBlockingQueue&lt;&gt;(<span class="hljs-number">5</span>), <span class="hljs-comment">// Bounded queue</span>
    <span class="hljs-keyword">new</span> ThreadPoolExecutor.AbortPolicy() <span class="hljs-comment">// Rejection handler</span>
);
</code></pre>
<p>More Cases and Other Approaches are covered in our <a target="_blank" href="https://interview.lldcoding.com/dashboard?chapter=%5BNEW%5D+%F0%9F%93%9E+Call+Center+Queue+Concurrency+Problem-L2FwaS9jb250ZW50L0NhbGwtQ2VudGVyLVF1ZXVlLUNvbmN1cnJlbmN5LVByb2JsZW0uY2h1bmswLmVuY3J5cHRlZA%3D%3D">course</a>.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/7uimTkFGEcM">https://youtu.be/7uimTkFGEcM</a></div>
]]></description><link>https://lldcoding.com/call-center-queue-concurrency-problem</link><guid isPermaLink="true">https://lldcoding.com/call-center-queue-concurrency-problem</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Java]]></category><category><![CDATA[concurrency]]></category><category><![CDATA[interview]]></category><dc:creator><![CDATA[Subhahu Jain]]></dc:creator></item><item><title><![CDATA[🚀 Rocket Launch Countdown Sync]]></title><description><![CDATA[<p>Youre simulating a <strong>rocket launch system</strong>.</p>
<p>Before the rocket can launch, it must pass several <strong>system checks</strong> (e.g., fuel, navigation, engine, weather, etc.).</p>
<p>Each system is checked <strong>independently</strong> by a different thread.</p>
<p>👉 <strong>Only after all checks are complete</strong>, the <strong>main launch system</strong> can proceed and say:</p>
<blockquote>
<p> "All systems go. Launching!"</p>
</blockquote>
<h2 id="heading-solution-approaches"><strong>Solution Approaches</strong></h2>
<ol>
<li><h3 id="heading-basic-thread-join-approach"><strong>Basic Thread Join Approach</strong></h3>
<ol>
<li><p><strong>Create threads</strong> - One thread for each system check (fuel, navigation, etc.)</p>
</li>
<li><p><strong>Start all threads</strong> - All checks run simultaneously</p>
</li>
<li><p><strong>Wait for completion</strong> - Main thread waits until all checks finish</p>
</li>
<li><p><strong>Launch</strong> - Only proceed if all checks were successful</p>
</li>
</ol>
</li>
</ol>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">RocketLaunchBasic</span> </span>{

    <span class="hljs-comment">// Task for checking individual systems</span>
    <span class="hljs-keyword">static</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SystemCheck</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Runnable</span> </span>{
        <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> String systemName;

        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">SystemCheck</span><span class="hljs-params">(String name)</span> </span>{
            <span class="hljs-keyword">this</span>.systemName = name;
        }

        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">run</span><span class="hljs-params">()</span> </span>{
            <span class="hljs-keyword">try</span> {
                <span class="hljs-comment">// Simulate check time (0-2 seconds)</span>
                System.out.println(<span class="hljs-string">" Checking "</span> + systemName + <span class="hljs-string">"..."</span>);
                Thread.sleep((<span class="hljs-keyword">long</span>)(Math.random() * <span class="hljs-number">2000</span>));
                System.out.println(systemName + <span class="hljs-string">" "</span>);
            } <span class="hljs-keyword">catch</span> (InterruptedException e) {
                System.out.println(systemName + <span class="hljs-string">"  (Interrupted)"</span>);
            }
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> <span class="hljs-keyword">throws</span> InterruptedException </span>{
        String[] systems = {<span class="hljs-string">"Fuel"</span>, <span class="hljs-string">"Navigation"</span>, <span class="hljs-string">"Engine"</span>, <span class="hljs-string">"Weather"</span>, <span class="hljs-string">"Comm"</span>};

        <span class="hljs-comment">// 1. Create threads for all systems</span>
        Thread[] threads = <span class="hljs-keyword">new</span> Thread[systems.length];
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; systems.length; i++) {
            threads[i] = <span class="hljs-keyword">new</span> Thread(<span class="hljs-keyword">new</span> SystemCheck(systems[i]));
        }

        <span class="hljs-comment">// 2. Start all checks in parallel</span>
        System.out.println(<span class="hljs-string">"🚀 Starting pre-launch checks..."</span>);
        <span class="hljs-keyword">for</span> (Thread t : threads) {
            t.start(); <span class="hljs-comment">// Launch parallel execution</span>
        }

        <span class="hljs-comment">// 3. Wait for all to complete</span>
        <span class="hljs-keyword">for</span> (Thread t : threads) {
            t.join(); <span class="hljs-comment">// Block until thread finishes</span>
        }

        <span class="hljs-comment">// 4. Final verification</span>
        System.out.println(<span class="hljs-string">"\n🔍 All checks completed!"</span>);
        System.out.println(<span class="hljs-string">"🚀 All systems go. Launching!"</span>);
    }
}
</code></pre>
<p><a target="_blank" href="https://mermaid.live/edit#pako:eNqFUk9PwjAU_yr1nTSZpFBg0AOJQbnhyZPZpekeW7VrZ9calfDdLRBggGAPTV_e71_btwRpcwQODX4ENBIflSicqDJD4qqF80qqWhhP5kKZl9KhyM97s4B6WqJ8P289i09VCK-suQB4MoUy2Gpu94Pd_WSy1-ek8ZF7e_cH6MTpGrTleQLb7tramsysIyhkSXzr1teivVlldjr_p7uKPgrYRqLJL77SoeDkQWsi1_SGSFvVGj3eQAKFUzlw7wImUKGrxLqE5VosA19ihRnweMxxIYL2GWRmFWnxo16trXZMZ0NRAl8I3cQq1Lnwu7nZQ2JQdFMbjAfeZRsJ4Ev4At5jtDNOu6Mh6457tE_ZMIFv4Kzf6bN0QGnKGB2xNF0l8LMxpZ1ROkgAc-Wtm2_HdTO1q19OluGj"><img src="https://mermaid.ink/img/pako:eNqFUk9PwjAU_yr1nTSZpFBg0AOJQbnhyZPZpekeW7VrZ9calfDdLRBggGAPTV_e71_btwRpcwQODX4ENBIflSicqDJD4qqF80qqWhhP5kKZl9KhyM97s4B6WqJ8P289i09VCK-suQB4MoUy2Gpu94Pd_WSy1-ek8ZF7e_cH6MTpGrTleQLb7tramsysIyhkSXzr1teivVlldjr_p7uKPgrYRqLJL77SoeDkQWsi1_SGSFvVGj3eQAKFUzlw7wImUKGrxLqE5VosA19ihRnweMxxIYL2GWRmFWnxo16trXZMZ0NRAl8I3cQq1Lnwu7nZQ2JQdFMbjAfeZRsJ4Ev4At5jtDNOu6Mh6457tE_ZMIFv4Kzf6bN0QGnKGB2xNF0l8LMxpZ1ROkgAc-Wtm2_HdTO1q19OluGj?type=png" alt /></a></p>
<h3 id="heading-failure-test-cases"><strong> Failure Test Cases</strong></h3>
<p><strong>1. Thread Never Completes (Deadlock)</strong></p>
<p>One system check hangs indefinitely. Lets say one of started thread never finish its run.</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">run</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">if</span> (systemName.equals(<span class="hljs-string">"Fuel"</span>)) {
        <span class="hljs-keyword">while</span>(<span class="hljs-keyword">true</span>) { <span class="hljs-comment">/* Infinite loop */</span> } 
    }
    <span class="hljs-comment">// ... normal check ...</span>
}
</code></pre>
<blockquote>
<p> Checking Fuel...<br /> Checking Navigation...<br />Navigation  ...<br />(Program hangs forever)</p>
</blockquote>
<p>To fix this, use join(timeout), which will only wait for specific amount of time</p>
<pre><code class="lang-java"><span class="hljs-keyword">for</span> (Thread t : threads) {
    t.join(<span class="hljs-number">3000</span>); <span class="hljs-comment">// Wait max 3 seconds</span>
    <span class="hljs-keyword">if</span> (t.isAlive()) {
        System.out.println(<span class="hljs-string">" "</span> + systemName + <span class="hljs-string">" timeout!"</span>);
        t.interrupt();
    }
}
</code></pre>
<p><strong>2. Exception in System Check</strong></p>
<p>Thread crashes during check.</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">run</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">if</span> (systemName.equals(<span class="hljs-string">"Navigation"</span>)) {
        <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> RuntimeException(<span class="hljs-string">"Sensor error"</span>);
    }
    <span class="hljs-comment">// ... normal check ...</span>
}
</code></pre>
<blockquote>
<p> Checking Fuel...<br /> Checking Navigation...<br /> Checking Engine...<br />Exception in thread "Thread-1" java.lang.RuntimeException: Sensor error<br />Fuel <br />Engine </p>
<p>🔍 All checks completed!<br />🚀 All systems go. Launching! ( Despite failure!)</p>
</blockquote>
<p>How we will fix this ?, will be covered in our <a target="_blank" href="https://interview.lldcoding.com/dashboard?chapter=%5BNEW%5D+%F0%9F%9A%80+Rocket+Launch+Countdown+Sync+Concurrency+Problem-L2FwaS9jb250ZW50L1JvY2tldC1MYXVuY2gtQ291bnRkb3duLVN5bmMtQ29uY3VycmVuY3ktUHJvYmxlbS5jaHVuazAuZW5jcnlwdGVk">course</a>.</p>
<p>More Approaches and Failing Test Cases will be covered in our <a target="_blank" href="https://interview.lldcoding.com/dashboard?chapter=%5BNEW%5D+%F0%9F%9A%80+Rocket+Launch+Countdown+Sync+Concurrency+Problem-L2FwaS9jb250ZW50L1JvY2tldC1MYXVuY2gtQ291bnRkb3duLVN5bmMtQ29uY3VycmVuY3ktUHJvYmxlbS5jaHVuazAuZW5jcnlwdGVk">course</a>.</p>
]]></description><link>https://lldcoding.com/rocket-launch-countdown-sync</link><guid isPermaLink="true">https://lldcoding.com/rocket-launch-countdown-sync</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Java]]></category><dc:creator><![CDATA[Subhahu Jain]]></dc:creator></item><item><title><![CDATA[🎮 Multiplayer Game Sync (e.g., "Among Us" Style) Concurrency Problem]]></title><description><![CDATA[<p>Let's model the synchronization challenges in a social deduction game like <em>Among Us</em>, where:</p>
<ul>
<li><p><strong>10-15 players</strong> (threads) interact in real-time</p>
</li>
<li><p><strong>Shared state</strong>: Player positions, tasks, voting, emergency meetings</p>
</li>
<li><p><strong>Critical requirements</strong>:</p>
<ul>
<li><p>No two players can report a body simultaneously</p>
</li>
<li><p>Emergency meetings must serialize discussions</p>
</li>
<li><p>Task progress must be atomic</p>
</li>
<li><p>Deadlock-free voting</p>
</li>
</ul>
</li>
</ul>
<h2 id="heading-solution-approaches"><strong>💡 Solution Approaches</strong></h2>
<ol>
<li><h3 id="heading-synchronized-everything"><strong>Synchronized Everything</strong></h3>
</li>
</ol>
<p>This is the simplest way to make your multiplayer game thread-safe, perfect for beginners learning concurrency. Let's break it down completely.</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Game</span> </span>{
    <span class="hljs-comment">// Shared game state</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> playersOnline = <span class="hljs-number">0</span>;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">boolean</span> gameStarted = <span class="hljs-keyword">false</span>;

    <span class="hljs-comment">// All methods are synchronized</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">synchronized</span> <span class="hljs-keyword">void</span> <span class="hljs-title">playerJoin</span><span class="hljs-params">()</span> </span>{
        playersOnline++;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">synchronized</span> <span class="hljs-keyword">void</span> <span class="hljs-title">startGame</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">if</span> (playersOnline &gt;= <span class="hljs-number">4</span>) {
            gameStarted = <span class="hljs-keyword">true</span>;
        }
    }
}
</code></pre>
<p><a target="_blank" href="https://mermaid.live/edit#pako:eNq9UsFOAjEQ_ZVmThJWsrsFFnogIUCMihJRL2YvDR2gyW67lq6KhJ9Q7_6in2CXBUNUDl7soenMe_PeSzormGiBwGCB9zmqCfYlnxmexoq4k3Fj5URmXFlyMzfIRXAICH8CJzzFslveW4XjTqdAGMkSvkRzpqU6qpSMS22R6Ac0pGR8vL-9kOGod066vavb0_GgX_IK9JvMYqQSqbBaJUdKP5Kgssd01K03I32t8KDZa2k2HgwH3eud2X748F_Ch7-GD_8WHjyYGSmAWZOjBymalBclrAqFGOwc3fcAc0-BU54nNoZYrd2Y-7w7rdPdpNH5bA5sypOFq_JMcLvbkq-uQSXQ9HSuLLAw3GgAW8GTq6hfa0dBq0mDdujXfdr0YAmM1mt1GjV8P6LUb9EoWnvwvHH1a62o4QEKabW5KLdzs6TrTxNE2FQ"><img src="https://mermaid.ink/img/pako:eNq9UsFOAjEQ_ZVmThJWsrsFFnogIUCMihJRL2YvDR2gyW67lq6KhJ9Q7_6in2CXBUNUDl7soenMe_PeSzormGiBwGCB9zmqCfYlnxmexoq4k3Fj5URmXFlyMzfIRXAICH8CJzzFslveW4XjTqdAGMkSvkRzpqU6qpSMS22R6Ac0pGR8vL-9kOGod066vavb0_GgX_IK9JvMYqQSqbBaJUdKP5Kgssd01K03I32t8KDZa2k2HgwH3eud2X748F_Ch7-GD_8WHjyYGSmAWZOjBymalBclrAqFGOwc3fcAc0-BU54nNoZYrd2Y-7w7rdPdpNH5bA5sypOFq_JMcLvbkq-uQSXQ9HSuLLAw3GgAW8GTq6hfa0dBq0mDdujXfdr0YAmM1mt1GjV8P6LUb9EoWnvwvHH1a62o4QEKabW5KLdzs6TrTxNE2FQ?type=png" alt /></a></p>
<p><strong>What "synchronized" Actually Does</strong></p>
<ol>
<li><p><strong>Lock Acquisition</strong>: When a thread enters any synchronized method:</p>
<ul>
<li><p>It acquires the object's <strong>intrinsic lock</strong> (also called the monitor lock)</p>
</li>
<li><p>Other threads must wait if the lock is held</p>
</li>
</ul>
</li>
<li><p><strong>Memory Visibility</strong>:</p>
<ul>
<li><p>When the lock is released, all changes become visible to other threads</p>
</li>
<li><p>When the lock is acquired, it sees the latest changes</p>
</li>
</ul>
</li>
<li><p><strong>Atomic Execution</strong>:</p>
<ul>
<li>The entire method runs without interruption from other threads</li>
</ul>
</li>
</ol>
<h2 id="heading-test-cases"><strong>Test Cases</strong></h2>
<h3 id="heading-1-normal-operation-single-thread"><strong>1. Normal Operation (Single Thread)</strong></h3>
<p><strong>Scenario</strong>: One player joins the game<br /><strong>Expected</strong>: Counter increments correctly</p>
<p><a target="_blank" href="https://mermaid.live/edit#pako:eNp1UcFOAjEQ_ZVmThBW0qXIQg8kRhMTI5oQT2YvzXaAxt126bZGJFz9APTuv_EFfoJdVsRonEPTN-_NvMzMGjIjEThUuPSoM7xQYm5FkWoSohTWqUyVQjsyEUrfLSwK-Ze7FAU22eY9ak_G45rkpMzFCu2VUbrVbkQ3xiExj2hJo_h4f9uSa5M9kLNs6ZXFL6Oa_dWmutW50tjpkBbdvWzj9g9lkB7tOZmi81ZX_1q-NpZTzFFUKCGCuVUSuLMeIyjQFqKGsK47pOAWGEYFHr4SZ8LnLoVUb0JZWMS9McWh0ho_XwCfibwKyJdSuMNuv7MWtUR7brx2wHuDfQ_ga3gKiNHuKImHAxaPerRPWWBXwFm_22fJKaUJY3TIkmQTwfPelXaHdf4YcQQolTN20hx4f-fNJ1J5n4U"><img src="https://mermaid.ink/img/pako:eNp1UcFOAjEQ_ZVmThBW0qXIQg8kRhMTI5oQT2YvzXaAxt126bZGJFz9APTuv_EFfoJdVsRonEPTN-_NvMzMGjIjEThUuPSoM7xQYm5FkWoSohTWqUyVQjsyEUrfLSwK-Ze7FAU22eY9ak_G45rkpMzFCu2VUbrVbkQ3xiExj2hJo_h4f9uSa5M9kLNs6ZXFL6Oa_dWmutW50tjpkBbdvWzj9g9lkB7tOZmi81ZX_1q-NpZTzFFUKCGCuVUSuLMeIyjQFqKGsK47pOAWGEYFHr4SZ8LnLoVUb0JZWMS9McWh0ho_XwCfibwKyJdSuMNuv7MWtUR7brx2wHuDfQ_ga3gKiNHuKImHAxaPerRPWWBXwFm_22fJKaUJY3TIkmQTwfPelXaHdf4YcQQolTN20hx4f-fNJ1J5n4U?type=png" alt /></a></p>
<pre><code class="lang-java">Game game = <span class="hljs-keyword">new</span> Game();
game.playerJoin();
<span class="hljs-keyword">assert</span> game.getPlayersOnline() == <span class="hljs-number">1</span>;  <span class="hljs-comment">// Passes</span>
</code></pre>
<h3 id="heading-2-concurrent-joins-race-condition-prevented"><strong>2. Concurrent Joins (Race Condition Prevented)</strong></h3>
<p><strong>Scenario</strong>: Two players join simultaneously<br /><strong>Expected</strong>: Counter shows 2 without corruption</p>
<p><a target="_blank" href="https://mermaid.live/edit#pako:eNqVUk1rAjEQ_SthTha3kt1VV3MQ-gGF0g8QT8VL3Iy6dDfRbFJqxWtPPdleS_-bv6A_oVlXRVAPzSFk5r1584bMHGIlEBjkOLUoY7xO-EjzrC-JOxOuTRInEy4N6Y01cuGfAoJD4IZnWGbLe6Nw3ukUCCOTlM9Q36pEVs5KxoMySNQLalIyfn--luROxc_kIp7aRKMggxnp-ft6wT_0Vt8fpdylzWek0gvIIHVhvqEXpJ1az98q5o8yTSRWq6RCV-9Lf5_t6JuxGOmisVrmJ0f5LHt3MUWeozjWMyAjNDkpTB2BD-z4zk5w1E6wswMejHQigBlt0YMMdcaLEOZFXR_MGN03AXNPgUNuU9OHvly4MveJT0pl20qt7GgMbMjT3EV2IrjZbssuq1EK1FfKSgMspGsNYHN4BRaEtNaO_FYz9NsBrdOw6cHMkeq1ehg1KI3CkLbCKFp48LbuSmutqOEBisQofV9u6XpZF3_d698-"><img src="https://mermaid.ink/img/pako:eNqVUk1rAjEQ_SthTha3kt1VV3MQ-gGF0g8QT8VL3Iy6dDfRbFJqxWtPPdleS_-bv6A_oVlXRVAPzSFk5r1584bMHGIlEBjkOLUoY7xO-EjzrC-JOxOuTRInEy4N6Y01cuGfAoJD4IZnWGbLe6Nw3ukUCCOTlM9Q36pEVs5KxoMySNQLalIyfn--luROxc_kIp7aRKMggxnp-ft6wT_0Vt8fpdylzWek0gvIIHVhvqEXpJ1az98q5o8yTSRWq6RCV-9Lf5_t6JuxGOmisVrmJ0f5LHt3MUWeozjWMyAjNDkpTB2BD-z4zk5w1E6wswMejHQigBlt0YMMdcaLEOZFXR_MGN03AXNPgUNuU9OHvly4MveJT0pl20qt7GgMbMjT3EV2IrjZbssuq1EK1FfKSgMspGsNYHN4BRaEtNaO_FYz9NsBrdOw6cHMkeq1ehg1KI3CkLbCKFp48LbuSmutqOEBisQofV9u6XpZF3_d698-?type=png" alt /></a></p>
<pre><code class="lang-java">Game game = <span class="hljs-keyword">new</span> Game();

Thread t1 = <span class="hljs-keyword">new</span> Thread(() -&gt; game.playerJoin());
Thread t2 = <span class="hljs-keyword">new</span> Thread(() -&gt; game.playerJoin());

t1.start();
t2.start();
t1.join();
t2.join();

<span class="hljs-keyword">assert</span> game.getPlayersOnline() == <span class="hljs-number">2</span>;  <span class="hljs-comment">// Always passes</span>
</code></pre>
<h3 id="heading-3-mixed-operations-join-start-game"><strong>3. Mixed Operations (Join + Start Game)</strong></h3>
<p><strong>Scenario</strong>: One joins while another tries to start game<br /><strong>Expected</strong>: Game starts only if 4 players</p>
<p><a target="_blank" href="https://mermaid.live/edit#pako:eNp1UktuwjAQvYo1qyBSFAgQsCqkfqRKVT8S7arKxk0GiJrY4NhVKWLbVVe026p34wQ9Qm0CgVLhhTWfN-_N2DODSMQIFHKcaOQRnidsKFkWcmLOmEmVRMmYcUUuRcLvRxJZ_D93p4xzKHnBMiyixb0lOur1bJKSccqmKG3CqRSgG6GQiGeUpED8fH8uyJWInshJNNGJxLXQjnLJltuYNQ-RLb_eC65TnU-J85gaO19jLWKvr_yWpwnHapU43vJtUd9FGuh2Hkr6qLTk-cEZPgrdPqbI8s0MfyTL5kk0QtMWiYQ2j-jUyTFp7invDF9KE2doi7lQBRXGFXBhKJMYqJIaXchQZsy6MLN0IagRmh8CaswYB0ynKoSQz02Z-b8HIbJNpRR6OAI6YGluPD2OmdrsSxmVyGOUZ7ZpoH5zxQF0Bi9AG75X6wb1Ttuvdxte0_PbLkwtqNb0g5bnBb7vdfwgmLvwulL1ap2g5QLGiRLyutjT1brOfwHOc-PU"><img src="https://mermaid.ink/img/pako:eNp1UktuwjAQvYo1qyBSFAgQsCqkfqRKVT8S7arKxk0GiJrY4NhVKWLbVVe026p34wQ9Qm0CgVLhhTWfN-_N2DODSMQIFHKcaOQRnidsKFkWcmLOmEmVRMmYcUUuRcLvRxJZ_D93p4xzKHnBMiyixb0lOur1bJKSccqmKG3CqRSgG6GQiGeUpED8fH8uyJWInshJNNGJxLXQjnLJltuYNQ-RLb_eC65TnU-J85gaO19jLWKvr_yWpwnHapU43vJtUd9FGuh2Hkr6qLTk-cEZPgrdPqbI8s0MfyTL5kk0QtMWiYQ2j-jUyTFp7invDF9KE2doi7lQBRXGFXBhKJMYqJIaXchQZsy6MLN0IagRmh8CaswYB0ynKoSQz02Z-b8HIbJNpRR6OAI6YGluPD2OmdrsSxmVyGOUZ7ZpoH5zxQF0Bi9AG75X6wb1Ttuvdxte0_PbLkwtqNb0g5bnBb7vdfwgmLvwulL1ap2g5QLGiRLyutjT1brOfwHOc-PU?type=png" alt /></a></p>
<pre><code class="lang-java"><span class="hljs-comment">//  Without synchronization:</span>
<span class="hljs-keyword">if</span> (playersOnline &gt;= <span class="hljs-number">4</span>) {  <span class="hljs-comment">// Race condition</span>
    gameStarted = <span class="hljs-keyword">true</span>;
}
</code></pre>
<h2 id="heading-critical-risks"><strong>Critical Risks</strong></h2>
<p>All Critical Risks and other approaches will be covered in our <a target="_blank" href="https://interview.lldcoding.com/dashboard?chapter=%5BNEW%5D+%F0%9F%8E%AE+Multiplayer+Game+Sync+Concurrency+Problem-L2FwaS9jb250ZW50L011bHRpcGxheWVyLUdhbWUtU3luYy1Db25jdXJyZW5jeS1Qcm9ibGVtLmNodW5rMC5lbmNyeXB0ZWQ%3D">course</a>.</p>
]]></description><link>https://lldcoding.com/multiplayer-game-sync-eg-among-us-style-concurrency-problem</link><guid isPermaLink="true">https://lldcoding.com/multiplayer-game-sync-eg-among-us-style-concurrency-problem</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Java]]></category><dc:creator><![CDATA[Subhahu Jain]]></dc:creator></item><item><title><![CDATA[🏦 Bank Transaction Concurrency Problem]]></title><description><![CDATA[<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1752091707245/7e84d228-f25b-4f69-8d36-bd38ea8a9de1.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-problem-statement"><strong>Problem Statement</strong></h3>
<ul>
<li><p>Multiple threads (ATM users, online banking) access <strong>shared bank accounts</strong>.</p>
</li>
<li><p>Operations:</p>
<ul>
<li><p><code>deposit(amount)</code></p>
</li>
<li><p><code>withdraw(amount)</code></p>
</li>
<li><p><code>getBalance()</code></p>
</li>
</ul>
</li>
<li><p><strong>Requirements</strong>:</p>
<ol>
<li><p><strong>Thread-safe</strong>: No race conditions during concurrent transactions.</p>
</li>
<li><p><strong>Consistency</strong>: Balance never goes negative (unless overdraft allowed).</p>
</li>
<li><p><strong>Deadlock-free</strong>: No circular waits between accounts (e.g., transfer between A and B).</p>
</li>
</ol>
</li>
</ul>
<h2 id="heading-solution-approaches"><strong>💡 Solution Approaches</strong></h2>
<h3 id="heading-1-basic-thread-safe-account-synchronized-methods"><strong>1. Basic Thread-Safe Account (Synchronized Methods)</strong></h3>
<p>To make the <code>BankAccount</code> thread-safe, we start by marking the <code>deposit</code>, <code>withdraw</code>, and <code>getBalance</code> methods as <code>synchronized</code> so only one thread can access them at a time per object.</p>
<h3 id="heading-key-mechanics"><strong>Key Mechanics</strong></h3>
<ul>
<li><p>Every Java object has an <strong>intrinsic lock</strong> (monitor).</p>
</li>
<li><p><code>synchronized</code> methods acquire this lock before execution.</p>
</li>
<li><p>Only <strong>one thread</strong> can hold the lock at a time  all other threads block.</p>
</li>
</ul>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">In Synchronized Method: Two threads cant execute <code>deposit()</code> and <code>withdraw()</code> at the same time <strong>on the same object</strong>, so <code>balance</code> remains consistent.</div>
</div>

<ul>
<li><div data-node-type="callout">
  <div data-node-type="callout-emoji">💡</div>
  <div data-node-type="callout-text"> However, if two threads operate on <strong>different objects</strong>, synchronization won't help because each object has a different lock.</div>
  </div>


</li>
</ul>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BankAccount</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">double</span> balance;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">synchronized</span> <span class="hljs-keyword">void</span> <span class="hljs-title">deposit</span><span class="hljs-params">(<span class="hljs-keyword">double</span> amount)</span> </span>{
        balance += amount;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">synchronized</span> <span class="hljs-keyword">void</span> <span class="hljs-title">withdraw</span><span class="hljs-params">(<span class="hljs-keyword">double</span> amount)</span> <span class="hljs-keyword">throws</span> InsufficientFundsException </span>{
        <span class="hljs-keyword">if</span> (balance &lt; amount) <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> InsufficientFundsException();
        balance -= amount;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">synchronized</span> <span class="hljs-keyword">double</span> <span class="hljs-title">getBalance</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> balance;
    }
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1752090713647/839f7b59-9904-479c-90b3-fd2a0e96b593.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-case-1-simple-deposit-withdraw-no-conflict"><strong>Case 1: Simple Deposit-Withdraw (No Conflict)</strong></h3>
<pre><code class="lang-java">BankAccount account = <span class="hljs-keyword">new</span> BankAccount();
<span class="hljs-comment">// Thread 1</span>
account.deposit(<span class="hljs-number">100</span>);  <span class="hljs-comment">//  Balance = 100</span>
<span class="hljs-comment">// Thread 2</span>
account.withdraw(<span class="hljs-number">30</span>);   <span class="hljs-comment">//  Balance = 70</span>
</code></pre>
<p><a target="_blank" href="https://mermaid.live/edit#pako:eNpFUMtugzAQ_BVrzxCZV1xbaqWG9NZe2pwKHFy8ASSwkWNEW8S_F4jSzGlnZ2e0mglKoxAEnFszlrW0jry-55oseM4-3MIF-ZKt1CU-0oL4_hM5ZKdAEIW9uTSOBJQW1_vDpqbZKRRkbFytrBxJdFPTTT1mL1rdExktwIPKNgqEswN60KHt5EphWn05uBo7zEEso8bBWdnmkOt5sfVSfxrT3ZzWDFUN4izby8KGXkmHx0ZWVnb_W4taoU3NoB2IIAm3EBATfIPw6Y6uiHnMOOV7FlEecM49-FnEeMeS5IHRIAloyFnE9-iz2YPf7QM9tK0HqBpn7Nu1z63W-Q9YTmmd"><img src="https://mermaid.ink/img/pako:eNpFUMtugzAQ_BVrzxCZV1xbaqWG9NZe2pwKHFy8ASSwkWNEW8S_F4jSzGlnZ2e0mglKoxAEnFszlrW0jry-55oseM4-3MIF-ZKt1CU-0oL4_hM5ZKdAEIW9uTSOBJQW1_vDpqbZKRRkbFytrBxJdFPTTT1mL1rdExktwIPKNgqEswN60KHt5EphWn05uBo7zEEso8bBWdnmkOt5sfVSfxrT3ZzWDFUN4izby8KGXkmHx0ZWVnb_W4taoU3NoB2IIAm3EBATfIPw6Y6uiHnMOOV7FlEecM49-FnEeMeS5IHRIAloyFnE9-iz2YPf7QM9tK0HqBpn7Nu1z63W-Q9YTmmd?type=png" alt /></a></p>
<h3 id="heading-case-2-concurrent-deposits-lost-update-problem-prevented"><strong>Case 2: Concurrent Deposits (Lost Update Problem Prevented)</strong></h3>
<p><a target="_blank" href="https://mermaid.live/edit#pako:eNp9kT1OxDAQha8STQVSsrKzyQa72AJo6bZCaax42I2U2MGxJSBKywF26bkbJ-AIOD-LkCBM5XnvzSdrpoNCSwQOLT46VAXelmJvRJ2rwFcjjC2LshHKBjv6hxb_1q5FJTwnV5O1o9F2O2s8-Hx_OwYSG92W9oIScjmFZv9nkgQfr8fARxYwp1mPF_HpP3TPnfgpWeCcIIS9KSVwaxyGUKOpxdBCN0zkYA9YYw7cPxU6a0SVQ656P-bXcK91fZ402u0PwB9E1frONVLY85a_VYNKornRTlngNI1HCPAOnoBHZEWGSliSMcI22ZowyhgL4dmbySpL06uM0JSSmGVrtsEo60N4GX-gXFWFgLK02txNhx7v3X8BlfuhJw"><img src="https://mermaid.ink/img/pako:eNp9kT1OxDAQha8STQVSsrKzyQa72AJo6bZCaax42I2U2MGxJSBKywF26bkbJ-AIOD-LkCBM5XnvzSdrpoNCSwQOLT46VAXelmJvRJ2rwFcjjC2LshHKBjv6hxb_1q5FJTwnV5O1o9F2O2s8-Hx_OwYSG92W9oIScjmFZv9nkgQfr8fARxYwp1mPF_HpP3TPnfgpWeCcIIS9KSVwaxyGUKOpxdBCN0zkYA9YYw7cPxU6a0SVQ656P-bXcK91fZ402u0PwB9E1frONVLY85a_VYNKornRTlngNI1HCPAOnoBHZEWGSliSMcI22ZowyhgL4dmbySpL06uM0JSSmGVrtsEo60N4GX-gXFWFgLK02txNhx7v3X8BlfuhJw?type=png" alt /></a></p>
<h3 id="heading-case-3-overdraft-prevention"><strong>Case 3: Overdraft Prevention</strong></h3>
<pre><code class="lang-java"><span class="hljs-comment">// Thread 1</span>
account.withdraw(<span class="hljs-number">150</span>);  <span class="hljs-comment">//  Fails (balance=100)</span>
<span class="hljs-comment">// Thread 2</span>
account.getBalance();   <span class="hljs-comment">//  Returns 100 (consistent read)</span>
</code></pre>
<p><a target="_blank" href="https://mermaid.live/edit#pako:eNo9kMFugzAMhl8l8hmqhJayRNqkUXrcZeI06CEDF5AgQV4iulV99wHt5pPtz79t_VeobI2g4NzbqWo1OZZnpWFzvBafutemwmfB-YmF4QtLi1woNnWurUlPTMT89Jhd8aHII8UadOld-IDpCrMib8lO7HipcHSdNQ96WOmxeEfnybDlFgTQUFeDcuQxgAFp0EsJ10VSgmtxwBLUnBr0jnRfQmlus2zU5sPa4U9J1jctqLPuv-bKj7V2mHW6IT38dwlNjXSw3jhQIo7WJaCucAEV8g1fYid3ieRyn2y5FFLKAL5nuNskcfyUcBELHslkK_cYJrcAftYPjO_7ALDunKW3u8er1bdfo3ZvmQ"><img src="https://mermaid.ink/img/pako:eNo9kMFugzAMhl8l8hmqhJayRNqkUXrcZeI06CEDF5AgQV4iulV99wHt5pPtz79t_VeobI2g4NzbqWo1OZZnpWFzvBafutemwmfB-YmF4QtLi1woNnWurUlPTMT89Jhd8aHII8UadOld-IDpCrMib8lO7HipcHSdNQ96WOmxeEfnybDlFgTQUFeDcuQxgAFp0EsJ10VSgmtxwBLUnBr0jnRfQmlus2zU5sPa4U9J1jctqLPuv-bKj7V2mHW6IT38dwlNjXSw3jhQIo7WJaCucAEV8g1fYid3ieRyn2y5FFLKAL5nuNskcfyUcBELHslkK_cYJrcAftYPjO_7ALDunKW3u8er1bdfo3ZvmQ?type=png" alt /></a></p>
<h2 id="heading-where-it-fails-edge-cases"><strong>Where It Fails (Edge Cases)</strong></h2>
<h3 id="heading-problem-1-nested-operations-deadlock"><strong>Problem 1: Nested Operations Deadlock</strong></h3>
<p>Consider if we are going to use this Object and tranfering money from one account to another</p>
<pre><code class="lang-java">
<span class="hljs-comment">// Thread 1</span>
<span class="hljs-function"><span class="hljs-keyword">synchronized</span> <span class="hljs-keyword">void</span> <span class="hljs-title">transfer</span><span class="hljs-params">(BankAccount to, <span class="hljs-keyword">double</span> amount)</span> </span>{
    <span class="hljs-keyword">this</span>.withdraw(amount);    <span class="hljs-comment">// Already holds lock on 'this'</span>
    to.deposit(amount);      <span class="hljs-comment">// Needs lock on 'to'  DEADLOCK if another thread does reverse transfer</span>
}
</code></pre>
<p><a target="_blank" href="https://mermaid.live/edit#pako:eNpVUMlugzAQ_RVrzhAZAnHtQ6W0PaaXqlKliosFw6IaOxpsdQH-vUAXJe8085bR6I1QugpBQW3ce9lq8uz0VFi24DlhcXw7nVz5NkzseEW-6M4PrHY0sbtfIb10X5MX7iNE0FBXgfIUMIIeqdfrCuMaKcC32GMBahktBk_aFFDYeYmdtX11rv9LkgtNC6rWZli2cK60x4dON6T7f5bQVkj3LlgPKsnT7QioET5AxXzHV2QyE5LLg9hzmUgpI_hcxGwn8vxG8CRPeCrFXh4wFnMEX9sHNhgTAVadd_T4099W4_wNRhplVw"><img src="https://mermaid.ink/img/pako:eNpVUMlugzAQ_RVrzhAZAnHtQ6W0PaaXqlKliosFw6IaOxpsdQH-vUAXJe8085bR6I1QugpBQW3ce9lq8uz0VFi24DlhcXw7nVz5NkzseEW-6M4PrHY0sbtfIb10X5MX7iNE0FBXgfIUMIIeqdfrCuMaKcC32GMBahktBk_aFFDYeYmdtX11rv9LkgtNC6rWZli2cK60x4dON6T7f5bQVkj3LlgPKsnT7QioET5AxXzHV2QyE5LLg9hzmUgpI_hcxGwn8vxG8CRPeCrFXh4wFnMEX9sHNhgTAVadd_T4099W4_wNRhplVw?type=png" alt /></a></p>
<h3 id="heading-problem-2-liveness-issues-performance"><strong>Problem 2: Liveness Issues (Performance)</strong></h3>
<ul>
<li><p><strong>All operations serialize</strong> (even <code>getBalance()</code> blocks writes).</p>
</li>
<li><p>Under high contention, throughput plummets.</p>
</li>
</ul>
<h3 id="heading-problem-3-compound-actions-not-atomic"><strong>Problem 3: Compound Actions Not Atomic</strong></h3>
<pre><code class="lang-java"><span class="hljs-keyword">if</span> (account.getBalance() &gt;= <span class="hljs-number">100</span>) {  <span class="hljs-comment">// Race condition!</span>
    account.withdraw(<span class="hljs-number">100</span>);          <span class="hljs-comment">// Balance may change between check and withdraw</span>
}
<span class="hljs-comment">// Operation is not Atomic, may cause issue if any changes happen between two operations.</span>
</code></pre>
<p><strong>More Apporaches, Explanation and Fixes of above problem will covered in our</strong> <a target="_blank" href="https://interview.lldcoding.com/dashboard?chapter=%5BNEW%5D+%F0%9F%8F%A6+Bank+Transaction+Concurrency+Problem-L2FwaS9jb250ZW50L0JhbmstVHJhbnNhY3Rpb24tQ29uY3VycmVuY3ktUHJvYmxlbS5jaHVuazAuZW5jcnlwdGVk"><strong>course</strong></a><strong>.</strong></p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/pIytlccni7w">https://youtu.be/pIytlccni7w</a></div>
]]></description><link>https://lldcoding.com/bank-transaction-concurrency-problem</link><guid isPermaLink="true">https://lldcoding.com/bank-transaction-concurrency-problem</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Java]]></category><category><![CDATA[interview]]></category><category><![CDATA[concurrency]]></category><dc:creator><![CDATA[Subhahu Jain]]></dc:creator></item><item><title><![CDATA[🚂 Train Deadlock  Concurrency Problem]]></title><description><![CDATA[<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751915384032/99a99fbb-882d-4f80-aa3b-c78842dcf0e5.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-problem-statement"><strong>Problem Statement</strong></h3>
<ul>
<li><p>Multiple trains run on a <strong>shared circular track</strong> (like a subway loop).</p>
</li>
<li><p>Only <strong>one train can occupy a track segment at a time</strong> (mutual exclusion).</p>
</li>
<li><p>Trains must <strong>avoid collisions</strong> (race conditions) and <strong>deadlocks</strong> (gridlock where all trains are stuck waiting).</p>
</li>
<li><p><strong>Goal</strong>: Implement a thread-safe system where trains move without crashing or freezing.</p>
</li>
</ul>
<h2 id="heading-solution-approaches"><strong>💡 Solution Approaches</strong></h2>
<h3 id="heading-1-basic-version-using-semaphores"><strong>1. Basic Version (Using Semaphores)</strong></h3>
<ul>
<li><p>Each <strong>track segment</strong> is guarded by a <strong>semaphore</strong> (1 permit = available, 0 = occupied).</p>
</li>
<li><p>Trains <strong>acquire the next segments semaphore</strong> before moving.</p>
</li>
<li><p><strong>Risk</strong>: If all trains hold one segment and wait for the next  <strong>circular deadlock</strong>.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751914945095/c4491313-3cd5-4db3-b9e0-c807c40ca9af.png" alt class="image--center mx-auto" /></p>
<h4 id="heading-java-implementation"><strong>Java Implementation</strong></h4>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> java.util.concurrent.Semaphore;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TrainDeadlockBasic</span> </span>{
    <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> NUM_SEGMENTS = <span class="hljs-number">5</span>;
    <span class="hljs-keyword">static</span> Semaphore[] segments = <span class="hljs-keyword">new</span> Semaphore[NUM_SEGMENTS];

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-comment">// Initialize segments (all available initially)</span>
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; NUM_SEGMENTS; i++) {
            segments[i] = <span class="hljs-keyword">new</span> Semaphore(<span class="hljs-number">1</span>);
        }

        <span class="hljs-comment">// Create 3 trains (threads)</span>
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">3</span>; i++) {
            <span class="hljs-keyword">new</span> Thread(<span class="hljs-keyword">new</span> Train(i)).start();
        }
    }

    <span class="hljs-keyword">static</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Train</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Runnable</span> </span>{
        <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> id;
        <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> currentSegment;

        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Train</span><span class="hljs-params">(<span class="hljs-keyword">int</span> id)</span> </span>{
            <span class="hljs-keyword">this</span>.id = id;
            <span class="hljs-keyword">this</span>.currentSegment = id % NUM_SEGMENTS; <span class="hljs-comment">// Start at different segments</span>
        }

        <span class="hljs-meta">@Override</span>
        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">run</span><span class="hljs-params">()</span> </span>{
            <span class="hljs-keyword">while</span> (<span class="hljs-keyword">true</span>) {
                <span class="hljs-keyword">try</span> {
                    <span class="hljs-keyword">int</span> nextSegment = (currentSegment + <span class="hljs-number">1</span>) % NUM_SEGMENTS;

                    System.out.printf(<span class="hljs-string">"Train %d WAITING for segment %d\n"</span>, id, nextSegment);
                    segments[nextSegment].acquire(); <span class="hljs-comment">// Request next segment</span>
                    System.out.printf(<span class="hljs-string">"Train %d ENTERED segment %d\n"</span>, id, nextSegment);

                    Thread.sleep(<span class="hljs-number">1000</span>); <span class="hljs-comment">// Simulate travel time</span>

                    segments[currentSegment].release(); <span class="hljs-comment">// Leave current segment</span>
                    System.out.printf(<span class="hljs-string">"Train %d LEFT segment %d\n"</span>, id, currentSegment);

                    currentSegment = nextSegment;
                } <span class="hljs-keyword">catch</span> (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        }
    }
}
</code></pre>
<h4 id="heading-problem-deadlock-risk"><strong> Problem: Deadlock Risk!</strong></h4>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751914017206/8c167091-37d0-4a62-ace2-e7dcedf427eb.png" alt="LLDcoding.com" class="image--center mx-auto" /></p>
<ul>
<li><p>If all trains hold their current segment and wait for the next  <strong>system freezes</strong>.</p>
</li>
<li><p>Example:</p>
<ul>
<li><p>Train 0 holds S0, waits for S1.</p>
</li>
<li><p>Train 1 holds S1, waits for S2.</p>
</li>
<li><p>Train 2 holds S2, waits for S0.<br />   <strong>Circular deadlock!</strong></p>
</li>
</ul>
</li>
</ul>
<p>Fix for above mentioned problem and more apporaches will be covered in our <a target="_blank" href="https://interview.lldcoding.com/dashboard?chapter=%5BNEW%5D+%F0%9F%9A%82+Train+Deadlock+Concurrency+Problem-L2FwaS9jb250ZW50L1RyYWluLURlYWRsb2NrLUNvbmN1cnJlbmN5LVByb2JsZW0uY2h1bmswLmVuY3J5cHRlZA%3D%3D">course</a></p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/Ylrkuwh-DeE">https://youtu.be/Ylrkuwh-DeE</a></div>
]]></description><link>https://lldcoding.com/train-deadlock-concurrency-problem</link><guid isPermaLink="true">https://lldcoding.com/train-deadlock-concurrency-problem</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Java]]></category><category><![CDATA[concurrency]]></category><dc:creator><![CDATA[Subhahu Jain]]></dc:creator></item><item><title><![CDATA[🚦 Traffic Light Concurrency Problem]]></title><description><![CDATA[<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751749684175/5d4d2fc1-9a5f-4d9a-8ece-e096710b3c78.jpeg" alt class="image--center mx-auto" /></p>
<p><strong>Problem Statement:</strong><br />Simulate a traffic intersection where:</p>
<ul>
<li><p>Multiple <strong>roads</strong> (threads) lead to a <strong>single intersection</strong> (shared resource).</p>
</li>
<li><p>Only <strong>one direction</strong> of traffic can pass at a time (mutual exclusion).</p>
</li>
<li><p>Traffic lights (<strong>semaphores/locks</strong>) control access to avoid accidents (race conditions).</p>
</li>
<li><p><strong>Bonus</strong>: Add turn lanes, pedestrian crossings, or emergency vehicle priority.</p>
</li>
</ul>
<h3 id="heading-possible-solutions-amp-approaches"><strong>💡 Possible Solutions &amp; Approaches</strong></h3>
<ol>
<li><h3 id="heading-basic-version-4-way-intersection"><strong>Basic Version (4-Way Intersection)</strong></h3>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751751323279/cb02d1cb-8247-4909-b114-6469943a574a.png" alt class="image--center mx-auto" /></p>
<p> At a busy four-way intersection, there's <strong>no traffic light</strong>, but a smart <strong>controller</strong> is in charge. Each road  North, South, East, and West  has a <strong>gatekeeper</strong> (a semaphore) that starts <strong>locked</strong> (red light 🚫).</p>
<p> The <strong>controller</strong> runs forever in a loop:</p>
<ol>
<li><p>It opens the <strong>North and South gates</strong> (green light 🟢) and lets one car from each direction pass.</p>
</li>
<li><p>After 5 seconds, it closes those gates (red light again 🔴).</p>
</li>
<li><p>Then it opens the <strong>East and West gates</strong> for 5 seconds and lets a car from each direction pass.</p>
</li>
<li><p>Repeat forever</p>
</li>
</ol>
</li>
</ol>
<p>    🚗 Meanwhile, from each direction, cars keep arriving  but they stop at the gate and <strong>wait</strong> (using <code>acquire()</code>) until the controller lets them go.</p>
<p>    Once the light turns green (via <code>release()</code>), a car goes through, <strong>thanks the controller</strong>, and may or may not leave the gate open for the next car (depending on whether the car calls <code>release()</code> again).</p>
<p>    This way, <strong>order and safety</strong> are maintained at the intersection using semaphores  and no crashes happen!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751754105549/11e15868-74d7-4dad-a869-6f8ec91720c4.png" alt class="image--center mx-auto" /></p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> java.util.concurrent.Semaphore;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TrafficLightBasic</span> </span>{
    <span class="hljs-comment">// Semaphores for each direction (initially 0 = RED)</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> Semaphore north = <span class="hljs-keyword">new</span> Semaphore(<span class="hljs-number">0</span>);
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> Semaphore south = <span class="hljs-keyword">new</span> Semaphore(<span class="hljs-number">0</span>);
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> Semaphore east = <span class="hljs-keyword">new</span> Semaphore(<span class="hljs-number">0</span>);
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> Semaphore west = <span class="hljs-keyword">new</span> Semaphore(<span class="hljs-number">0</span>);

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-comment">// Traffic light controller thread</span>
        Thread controller = <span class="hljs-keyword">new</span> Thread(() -&gt; {
            <span class="hljs-keyword">while</span> (<span class="hljs-keyword">true</span>) {
                <span class="hljs-keyword">try</span> {
                    System.out.println(<span class="hljs-string">"\n🟢 NORTH/SOUTH GREEN"</span>);
                    north.release(); <span class="hljs-comment">// Green for North</span>
                    south.release(); <span class="hljs-comment">// Green for South</span>
                    Thread.sleep(<span class="hljs-number">5000</span>); <span class="hljs-comment">// 5 sec green light</span>
                    north.acquire(); <span class="hljs-comment">// Back to red</span>
                    south.acquire();

                    System.out.println(<span class="hljs-string">"\n🟢 EAST/WEST GREEN"</span>);
                    east.release();
                    west.release();
                    Thread.sleep(<span class="hljs-number">5000</span>);
                    east.acquire();
                    west.acquire();
                } <span class="hljs-keyword">catch</span> (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        });
        controller.setDaemon(<span class="hljs-keyword">true</span>);
        controller.start();

        <span class="hljs-comment">// Simulate cars arriving from different directions</span>
        <span class="hljs-keyword">new</span> Thread(() -&gt; car(north, <span class="hljs-string">"North Car"</span>)).start();
        <span class="hljs-keyword">new</span> Thread(() -&gt; car(south, <span class="hljs-string">"South Car"</span>)).start();
        <span class="hljs-keyword">new</span> Thread(() -&gt; car(east, <span class="hljs-string">"East Car"</span>)).start();
        <span class="hljs-keyword">new</span> Thread(() -&gt; car(west, <span class="hljs-string">"West Car"</span>)).start();
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">car</span><span class="hljs-params">(Semaphore sem, String name)</span> </span>{
        <span class="hljs-keyword">while</span> (<span class="hljs-keyword">true</span>) {
            <span class="hljs-keyword">try</span> {
                sem.acquire(); <span class="hljs-comment">// Wait for green light</span>
                System.out.println(name + <span class="hljs-string">" is passing through!"</span>);
                Thread.sleep(<span class="hljs-number">1000</span>); <span class="hljs-comment">// Time to cross intersection</span>
                sem.release(); <span class="hljs-comment">// Not strictly needed if controller handles it</span>
            } <span class="hljs-keyword">catch</span> (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }
}
</code></pre>
<p>More Solution will be discussed in our <a target="_blank" href="https://interview.lldcoding.com/dashboard?chapter=Traffic+Light+Concurrency+Problem-L2FwaS9jb250ZW50L1RyYWZmaWMtTGlnaHQtQ29uY3VycmVuY3ktUHJvYmxlbS5jaHVuazAuZW5jcnlwdGVk">course</a>.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/GIizrrtgno4">https://youtu.be/GIizrrtgno4</a></div>
]]></description><link>https://lldcoding.com/traffic-light-concurrency-problem</link><guid isPermaLink="true">https://lldcoding.com/traffic-light-concurrency-problem</guid><category><![CDATA[Java]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[concurrency]]></category><dc:creator><![CDATA[Subhahu Jain]]></dc:creator></item></channel></rss>