๐ŸŽฎ Online Matchmaking (Real-Time Queue Handling) Concurrency Problem

Subhahu JainSubhahu Jain
2 min read

Problem

Simulate an online matchmaking system where:

  • Players join a matchmaking queue in real-time.

  • When enough players are available (say, 4 or 10), a match is created.

  • Players are then removed from the queue, and a game session is started.

Solution Approaches

Naive / Basic Implementation

we just keep a normal list of players waiting for a match.

import java.util.*;

public class NaiveMatchmaking {
    static final int PLAYERS_PER_MATCH = 4;
    static List<Integer> waitingPlayers = new ArrayList<>();

    public static void main(String[] args) {
        // Players joining (simulated)
        for (int i = 1; i <= 8; i++) {
            joinQueue(i);
        }
    }

    static void joinQueue(int playerId) {
        waitingPlayers.add(playerId);
        System.out.println("๐Ÿ™‹ Player #" + playerId + " joined queue.");

        if (waitingPlayers.size() >= PLAYERS_PER_MATCH) {
            startMatch();
        }
    }

    static void startMatch() {
        List<Integer> matchPlayers = waitingPlayers.subList(0, PLAYERS_PER_MATCH);
        System.out.println("๐ŸŽฎ Match started: " + matchPlayers);
        matchPlayers.clear(); // remove them from queue
    }
}

Problem โ€“ Concurrency Breaks This

Now, in real life:

  • Players join in parallel (multiple threads)

  • Matches are formed in real-time

  • The list waitingPlayers is not thread-safe โ†’ Race conditions happen:

    • Two threads may see enough players and start the same match twice.

    • Players may be skipped or duplicated.

    • Modifying the same list from multiple threads โ†’ ConcurrentModificationException.

Example failure scenario:

Thread 1: sees 4 players โ†’ starting match...
Thread 2: sees same 4 players โ†’ starting another match...

โ†’ First Fix โ€“ Add Locks (synchronized)

try to fix it by synchronizing the join method.

static synchronized void joinQueue(int playerId) {
    waitingPlayers.add(playerId);
    if (waitingPlayers.size() >= PLAYERS_PER_MATCH) {
        startMatch();
    }
}

static synchronized void startMatch() {
    List<Integer> matchPlayers = new ArrayList<>(waitingPlayers.subList(0, PLAYERS_PER_MATCH));
    System.out.println("๐ŸŽฎ Match started: " + matchPlayers);
    waitingPlayers.removeAll(matchPlayers);
}

โœ… This works for correctness.
โŒ But:

  • It blocks all player joins when one player is joining or a match is starting โ†’ slower.

  • If you scale to thousands of players, this becomes a bottleneck.

Better Approach

will be covered in our course.

0
Subscribe to my newsletter

Read articles from Subhahu Jain directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Subhahu Jain
Subhahu Jain