How would you handle concurrent access to parking spots in your design?
Fast recall
Quick revision
Core answer
Understanding of race conditions in multi-threaded environments and ability to apply Java concurrency primitives to prevent data corruption in shared state.
Ignoring thread safety entirely or synchronizing the entire ParkingLot class, which creates a single bottleneck and destroys throughput when multiple vehicles park simultaneously.
Explain lock granularity trade-offs—locking individual spots versus entire floors—and mention performance implications like contention vs overhead, or discuss using AtomicReference with compareAndSet for lock-free updates.
Interview-ready guide
Interview answer
The concurrency problem is two vehicles at two gates trying to take the same spot at the same instant. Both threads check that the spot is free, both see true, and both park — that's a classic check-then-act race condition, and it double-books the spot. The fix is to make the check and the claim a single atomic operation so only one thread can win.
The simplest version is to make the park method on ParkingSpot synchronized, so only one thread enters at a time. A nicer, lock-free version uses an AtomicReference for the occupying vehicle and calls compareAndSet from null to the vehicle — if two threads race, exactly one gets true back and the other has to look elsewhere. For the collection of spots, I'd use a ConcurrentHashMap instead of a plain HashMap so reads and writes are safe.
Lock granularity determines whether the safe design can still handle concurrent traffic. A common fresher mistake is to synchronize the whole ParkingLot or the entire park method, which means only one car can park anywhere at a time and throughput collapses. Instead I lock at the spot level — or at most the floor level — so cars on different floors don't block each other. And if I use an explicit ReentrantLock, I always release it in a finally block, otherwise an exception mid-operation leaves the lock held and the system deadlocks. The class-level design therefore needs both a spot invariant and a clear concurrency boundary.
For example, if Gate A and Gate B both try spot.tryOccupy(vehicle) for S-17, a compare-and-set from null to the vehicle lets one call return true and the other return false. The losing gate searches for another spot instead of issuing a second ticket.
How would you handle concurrent access to parking spots in your design
Direct Answer
Use synchronized methods or ReentrantLock around the check-and-occupy operation to prevent race conditions. The critical section is when a thread checks if a spot is available and then marks it occupied—two threads could both see the spot as free and try to take it. Store parking spots in ConcurrentHashMap for thread-safe lookups. Use AtomicBoolean or volatile for spot status flags to ensure visibility across threads.
Deep Dive & Architecture
The invariant is one active vehicle per spot
A thread-safe collection protects the collection structure, but it does not make “check free, then occupy” atomic. If those are separate calls, two gates can both observe FREE before either writes OCCUPIED.
One operation chooses the winner
ParkingSpot.tryOccupy(vehicle) should perform the check and state change together. It can synchronize on that spot, use a short ReentrantLock block, or call compareAndSet(null, vehicle) on an atomic reference. For example, if Gate A and Gate B race for S-17, only the successful atomic claim receives the ticket; the loser searches again.
The storage boundary needs the same guarantee
When several application instances share a database, a version column, conditional update, or unique active-reservation constraint provides the final protection. Locking the whole parking lot is simpler but serializes unrelated spots. Spot-level locking keeps the invariant while allowing different cars to occupy different spots concurrently.
Common Mistakes & Pitfalls
- Synchronizing the whole
ParkingLot— serializes all gates; kills throughput. Lock the spot, not the lot. HashMapfor shared spots —ConcurrentModificationExceptionunder concurrent writes; useConcurrentHashMap.ReentrantLockwithouttry/finally— an exception leaves the lock held forever (deadlock). Always unlock infinally.- Treating check and act as two steps — that gap is the race. Make it one atomic operation.
Check your understanding
Answer these without looking back at the article.
- Design a parking lot system. Walk me through your approach.
- How does the fee calculation work in your parking lot design?
- How would you extend the parking lot design for multiple locations?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.