There are many sources where you can get an idea of what JMM is about, but most of them still leave you with lots of
unanswered questions. How does that happens-before thing work? Does using
volatile result in
caches being dropped? Why do we even need a memory model in the first place?
This article is intended to give the readers a level of understanding which allows them to answer all of these questions. It will consist of two large parts; the first of them being a hardware-level outline of what's happening, and the second is indulging in some digging around OpenJDK sources and experimenting. Thus, even if you're not exactly into Java, the first part might still be of interest to you.