Multithreading Chat Server
- Published on
- 17 December 2025-2 min read
Java to Go: From Locks to Lock-Free
A legacy Java TCP chat server had a fundamental flaw: shared mutable state protected by locks. Rebuilt from scratch in Go using single-owner goroutines and message passing instead.
GoConcurrencyCSPDockerPrometheus
Problem → Solution
| Problem | Java | Go |
|---|---|---|
| Synchronization | Mutex-heavy, deadlock risk | No locks anywhere |
| I/O Model | Thread-per-connection, blocking | Goroutines, non-blocking channels |
| Shared State | Concurrent mutations, race conditions | Single Registry goroutine (sequential) |
| Backpressure | Threads block on queues | Drop slow clients, unblock writer |
| Race Safety | Manual review, hard to verify | go test -race (zero detections) |
Architecture: Registry Goroutine as Single Source of Truth
Client 1 (read) ──┐
Client 1 (write)──┤
├──> [Registry] <──────> [Shared State]
Client N (read) ──┤ (users, messages)
Client N (write)──┘
All mutations flow through Registry via channels (CSP).
No concurrent access. No locks. No races.
Features: Register username, broadcast, whisper (/w), list users (/users).
Evidence: Zero Data Races
go test -racepasses with zero detections across all state transitions- Test coverage: duplicate rejection, user list consistency, whisper routing
- Prometheus metrics: connected clients, message throughput, latency (p50/p95/p99)
- Grafana dashboard auto-loads with
docker-compose up --build
View on GitHub →
Previous Project← Conway's Game of Life: Parallel vs Distributed
Next ProjectConcurrent Order Book →