I knew the textbook answer but fumbled explaining the actual tradeoff under pressure.
Start by clarifying the distinct guarantees each provides: volatile ensures visibility and ordering for a single variable, while synchronized provides mutual exclusion and visibility for a block of code. Then explain that volatile is chosen when you need lightweight, lock-free visibility for a single variable without compound actions, and synchronized when you need atomicity for compound operations or coordination across multiple variables.
Pro tip: Emphasize that volatile is not a replacement for synchronized because it doesn't provide atomicity for compound actions like check-then-act; mention that in practice, you often combine volatile with other constructs (e.g., for flags or one-time initialization) and that java.util.concurrent utilities often supersede both.
Briefly state that volatile guarantees visibility and ordering for a single variable, while synchronized guarantees mutual exclusion and visibility for a block of code.
Determine whether the requirement is only visibility for a single variable (use volatile) or atomicity for compound actions or multiple variables (use synchronized).
Note that volatile is lighter-weight and non-blocking, while synchronized can cause contention and context switching, so volatile is preferable when it suffices.
Give scenarios: volatile for a status flag or one-time initialization; synchronized for incrementing a counter or updating multiple related fields.
Acknowledge that java.util.concurrent classes (e.g., AtomicInteger) often replace both, and that volatile is not a substitute for synchronized when atomicity is needed.
AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.