A race appears when a result depends on an uncontrolled interleaving. Splitting an update into a read and a write lets two workers use the same old value. A synchronized region can protect a compound update when every caller uses the same monitor. Visibility is a separate requirement: a value written by one thread needs a happens-before relationship before another thread can rely on reading it.
The browser runtime does not run native Java threads. You will trace explicit schedules and use real synchronized syntax on sequential work. These tasks let you test the state rule. They do not establish that an application is correct under every JVM schedule. For account transfers, choose a consistent lock order and name the invariant protected by the lock.