Interview Practice

Chapter 3 of 5

Visibility, atomicity and concurrent work

Identify the invariant and synchronization boundary before choosing an API.
Read aloud is unavailable in this browser. Reading preferences still work.

Visibility is different from atomicity

The Java memory model defines when writes become visible and the ordering guarantees of synchronization actions. A volatile field supports visibility and ordering for that field, but count++ still performs a read, arithmetic and write. synchronized protects a critical section; AtomicInteger exposes specific atomic actions. If a rule spans several fields or objects, individually atomic field updates may not preserve that rule.

Shared collections and overload

ConcurrentHashMap provides defined concurrent access and atomic per-key operations such as merge, but its mutable values and cross-key sequences need their own coordination. Executors also require a capacity and lifecycle policy. An unbounded backlog can hide overload until memory or latency collapses. Bound scarce resources, distinguish queue wait from execution time and propagate deadline/cancellation decisions deliberately.

Threads are not extra downstream capacity

Virtual threads are well suited to large numbers of waiting tasks, not faster CPU arithmetic. They do not increase a database pool size or a vendor quota. Version matters: JDK 24 removed the earlier monitor-related pinning limitation; native or foreign operations can still pin. CompletableFuture expresses composition, but blocking join calls and an unsuitable executor can erase its benefit. Measure the real workload before changing execution models.

Worked Java example

Illustrative snippet: imports, surrounding types or collaborators may be omitted. Read the assumptions before adapting it.

ConcurrentHashMap<String, Integer> counters = new ConcurrentHashMap<>();
void record(String route) {
    counters.merge(route, 1, Integer::sum);
}

Walkthrough

merge makes the update for one route atomic under concurrent callers. A get-then-put alternative can lose an increment if both callers read the old value. This design still needs a bounded set of route names: using raw user IDs or full URLs can grow the map indefinitely. Per-key atomicity does not provide a consistent snapshot across every route.

Practice it yourself

Design a bounded worker service. State what happens when the queue is full, a task exceeds its deadline and shutdown begins.

Check your reasoning

Choose a bounded queue and explicit rejection/backpressure policy, account for queue time in the deadline, make interruption/cancellation cooperative where possible, and stop admission before draining or cancelling work during shutdown. Do not promise cancellation of a remote operation that may already have committed.

Recall checklist

  • Explain the main invariant or contract without looking.
  • Trace the example and test an edge case.
  • State time, space, input variables and assumptions where relevant.
  • Explain one alternative and when you would choose it.

Read further