Learn Java multi-threading and resolve data and race conditions with volatile, atomics, and synchronized