Module 41
Concurrency-Aware Data Structures
What breaks when threads share data, and how Java fixes it: locks, atomics, latches, semaphores, blocking queues, concurrent maps and thread pools.
Every structure so far assumed one thread. Real servers run many threads at once, and a HashMap or a counter shared between them can silently lose updates or corrupt itself. Interviews for backend roles increasingly ask you to make a design thread-safe or to coordinate threads in a fixed order.
This module explains race conditions and the Java tools that prevent them (synchronized, atomics, locks and conditions), the coordination primitives (latches, semaphores, wait/notify), and the ready-made concurrent collections and executors you should reach for first. Problems are written so their results are deterministic and can be checked automatically.
Best after: Designing Data Structures
Where this shows up in real systems
- System Design · Topic 5.11 — Concurrent Cache — Locks, atomics and ConcurrentHashMap are what make a cache safe under many threads.
- System Design · Problem 4.15 — Rate Limiter (LLD) — A token bucket with lazy refill, made thread-safe.
- System Design · Topic 5.8 — Producer / Consumer — The blocking queue that producer-consumer systems are built on.
- System Design · Topic 5.5 — Race Conditions — Lost updates, locks and atomics with runnable examples.
- System Design · Topic 5.3 — Concurrent Data Structures / Atomics — ConcurrentHashMap, BlockingQueue and executors in practice.
- System Design · Topic 11.16 — Distributed Locking — The same mutual-exclusion ideas as in-process locks, stretched across machines.
Part 1
Learn the ideas
- 41.1Race Conditions, Locks and Atomicscount++ is three steps (read, add, write); two threads can interleave them and lose updates. synchronized makes a block run one thread at a time; atomics do the same for single variables without a lock.16 min
- 41.2Coordinating Threads: Latches, Semaphores, ConditionsCountDownLatch waits for events, Semaphore limits how many threads proceed, wait/notifyAll and Condition objects let threads sleep until a state changes. BlockingQueue packages the producer-consumer pattern.14 min
- 41.3Concurrent Collections and ExecutorsConcurrentHashMap gives thread-safe maps with atomic merge/compute. ExecutorService runs tasks on a pool of threads and returns Futures. Reach for these before writing locks yourself.12 min
Part 2
Solve the problems
Work through them in order. Each one shows the pattern it teaches.
Ordering threads with latches (or semaphores), whatever order they start in.
Turn-taking among several threads with a shared counter, wait() in a while loop and notifyAll().
A lock with two conditions: producers wait on "not full", consumers on "not empty".
Lazy refill on each request, guarded by a lock so concurrent requests can't overspend.
Split work into chunks, run them on a thread pool, and combine the Futures.