The Memory Model is difficult to understand, and difficult to apply. It is useful if you need to reason about the correctness of multi-threaded code, but you do not want to have to do this reasoning for every multi-threaded application that you write.
If you adopt the following principals when writing concurrent code in Java, you can largely avoid the need to resort to happens-before reasoning.
Lock
objects to synchronize access to state in mutable objects that need to be thread-safe1.Executor
/ ExecutorService
or the fork join framework rather than attempting to create manage threads directly.java.util.concurrent
versions of maps, sets, lists, queues and deques rather than external synchonization of non-concurrent collections.The general principle is to try to use Java’s built-in concurrency libraries rather than “rolling your own” concurrency. You can rely on them working, if you use them properly.
1 - Not all objects need to be thread safe. For example, if an object or objects is thread-confined (i.e. it is only accessible to one thread), then its thread-safety is not relevant.