š® Online Matchmaking (Real-Time Queue Handling) Concurrency Problem
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
waitingPlayersis 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.
