It guarantees that the value read was some value that was in the variable at some point. e.g. it prevents a value that toggles from 3 to 5 being read as 117. It also prevents writes from being eaten (e.g. an increment always actually occurs).
(It also guarantees happens-before for a given thread, so if a thread changes it from three to 5 and other threads are not changing it back, that thread will never read a 3 again. This also needs some level of synchronization)
This necessitates some level of synchronization.