The Java Memory ModelAlexander Martens
StructureWhat is a memory model about?Platform memory modelsAnnotation: Formal semanticsPro & ContraThe new Java Memory Model (JMM)HistoryAtomicity rulesOrdering rulesVisibility rulesPiggybacking on synchronizationPublicationInitialization safetyChangesImplementation sketch
What is a memory model about?A memory model defines the behavior of threads how to interact through shared mutual memory.Therefore you need rules forAtomicity: Which operations are atomic?Ordering: In which order do the operations happen?Visibility: When is the modified data visible to other processors?These depends on the memory model at processor level, because of the varying degrees of cache coherence across different architectures.
Platform memory models
Platform memory modelsdefines what guarantees programs can expect from the memoryAtomicity: Which operations are not interrupted by the scheduler?Ordering: In which situation are operations reordered to achieve maximum performance?Visibility: Which writes to shared mutual memory are visible to other processors at any given time?specifies memory barriers (special instructions of a processor) to enforce an ordering constraintSome processors exhibit a strong memory model, other processors exhibit a weaker memory model (different processors are able to see different values for the same memory location).
JMM and PMMJMM can be seen as an abstraction layer across different multiprocessor architectures.In dependence to the underlying hardware, the Java compiler deals with the differences by inserting memory barriers at the appropriate places to maintain the rules of the JMM.
Annotation: Formal semanticsTogether with the definition of single-threaded execution, the memory model specifies the formal semantics of a programming language.Typically, in a single-threaded environment the compiler is required to implement as-if-serial semantics.As-if-serial: All actions of a thread can be reordered for optimization, as long as the result is the same as if they are ordered in program order.
Pro & ContraProA programmer can reason about code execution.Atomicity and visibility is well-regulated.A data race can be prevented, because of ordering rules.A data race occurs, if a reads and writes of different threads on the same variable are not in a partial order.A compiler / processor is able to perform important optimizations, like loop fusion, in multi-threaded environment to achieve maximum performance.ContraThe memory model also leads to performance cost, because of locks and other communication stuff.
History1991: Oak was developed under the name "The Green Project" by James Goslip and other developers within 18 months. The project was initiated by Sun Microsystems to develop a kernel for executing safe, portable, object-oriented and multi-threaded software on set-top boxes. 1995: Java 1.0 has been published by Sun Microsystems.
History2004: The original memory model was updated through the Java Community Process, as Java Specification Request 133, for Java 5.0, because the old one prevented many runtime optimizations and it didn’t provide enough guarantees for code safety.
Atomicity rulesAccesses to variables of primitive types (excluding long and double) and reference variables are atomic.Accesses to volatile variables of primitive types (including long and double) and reference variables are atomic.Operations on atomic  variables in the package „java.util.concurrent.atomic“ are atomic, too.
Ordering rulesJMM defines an happens-before partially order for all instructions in a multi-threaded program.The order guarantees: Thread B will see the result of Thread A, if there exists a happens-before relation between B and A (because of corresponding visibility rules).If there exists a happens-before relation, the order of instructions will be reordered at will.
Happens-before orderProgram order ruleMonitor lock ruleVolatile variable ruleThread start ruleThread termination ruleInterruption ruleFinalizer ruleTransitivity
Visibility rulesThread ruleMonitor lock ruleVolatile variable ruleAtomic variable ruleFinal variable rule
Piggybacking on synchronizationPiggybacking on synchronization means combining the program order rule with the monitor lock rule or volatile variable rule concerning ordering and visibility of ordering and visibility, appearing in a code sequence.Pro: Not every method must be synchronized. Performance benefitA global order can be asserted by using a volatile variable as a guard.
PublicationThe absence of a happens-before order between publishing a shared object and accessing it leads to a partially constructed object.@NotThreadSafepublic class UnsafeLazyInitialization{	private static Resource resource;	public static Resource getInstance() {if (resource == null)				resource = new Resource();return resource;}}
Thread-safe lazy initilizationThread-safe lazy initialization is guaranteed by synchronization of the getInstance method.@ThreadSafepublic class SafeLazyInitialization{	private static Resource resource;	public synchronized static Resource getInstance() {if (resource == null)				resource = new Resource();return resource;}}
Double-checked lockingAntipattern (not thread safe), invented to reduce the impact of synchronization.In the original JMM synchronization was expensive concerning performance.Since JRE 5.0 it’s obsolete, because of a tuned JVM (especially JMM).Now it’s better to use thelazy initialization holder class idiom to gain performance, because it offers the same benefit and is easier to understand.
Double-checked locking@NotThreadSafepublic class DoubleCheckedLocking{	private static Resource resource;	public static Resource getInstance() {if (resource == null) {			synchronized (doubleCheckedLocking.class) {if (resource == null) 					resource = new Resource();}}}}
Lazy initialization holder class idiomcombines the safe lazy initialization with the lazy initialization holder class idiomdoes not require synchronization, because of eager class initialization idiom@ThreadSafepublic class ResourceFactory{	private static class ResourceHolder{		public static Resource resource= new Resource();}	public static Resource getResource() {return ResourceHolder.resource;}}
Initialization safetyAllows properly constructed immutable objects to be safely shared across threads without synchronization.Threads, obtaining a reference to that objects, are guaranteed to see up-to-date values of final fields.Initial writes aren’t reordered with accesses, coming after the final field is frozen.
ChangesAccesses to volatile variables won’t be reordered with any other memory operation.useful for using a volatile variable as a guardstatic int a = 0, b = 0;static int x = 0, y = 0;static volatile boolean initialized =false; //Thread Aa = 1;b = 1;initialized =true; //ThreadBwhile(!initialized){}x = a;y = b;
ChangesIntroduction of the happens-before orderThe initialization of final fields will never be reordered with operations following the finalization associated with the end of the constructor. Final means final.
Implementation sketchDependent on the underlying hardware platform model , the Java compiler insert the right memory barriers/fences, so that the Java memory model is valid. In a general model, the following fences exist:LoadLoadStoreStoreLoadStoreStoreLoad
Implementation sketchA synchronized block can be realized as follows:public class X {	private int a,i;	public void synchronized f(){LoadLoad;LoadStore;i= a;			a =i;StoreLoad;StoreStore;}}
Thank you for your attention! Questions?

The Java Memory Model

  • 1.
    The Java MemoryModelAlexander Martens
  • 2.
    StructureWhat is amemory model about?Platform memory modelsAnnotation: Formal semanticsPro & ContraThe new Java Memory Model (JMM)HistoryAtomicity rulesOrdering rulesVisibility rulesPiggybacking on synchronizationPublicationInitialization safetyChangesImplementation sketch
  • 3.
    What is amemory model about?A memory model defines the behavior of threads how to interact through shared mutual memory.Therefore you need rules forAtomicity: Which operations are atomic?Ordering: In which order do the operations happen?Visibility: When is the modified data visible to other processors?These depends on the memory model at processor level, because of the varying degrees of cache coherence across different architectures.
  • 4.
  • 5.
    Platform memory modelsdefineswhat guarantees programs can expect from the memoryAtomicity: Which operations are not interrupted by the scheduler?Ordering: In which situation are operations reordered to achieve maximum performance?Visibility: Which writes to shared mutual memory are visible to other processors at any given time?specifies memory barriers (special instructions of a processor) to enforce an ordering constraintSome processors exhibit a strong memory model, other processors exhibit a weaker memory model (different processors are able to see different values for the same memory location).
  • 6.
    JMM and PMMJMMcan be seen as an abstraction layer across different multiprocessor architectures.In dependence to the underlying hardware, the Java compiler deals with the differences by inserting memory barriers at the appropriate places to maintain the rules of the JMM.
  • 7.
    Annotation: Formal semanticsTogetherwith the definition of single-threaded execution, the memory model specifies the formal semantics of a programming language.Typically, in a single-threaded environment the compiler is required to implement as-if-serial semantics.As-if-serial: All actions of a thread can be reordered for optimization, as long as the result is the same as if they are ordered in program order.
  • 8.
    Pro & ContraProAprogrammer can reason about code execution.Atomicity and visibility is well-regulated.A data race can be prevented, because of ordering rules.A data race occurs, if a reads and writes of different threads on the same variable are not in a partial order.A compiler / processor is able to perform important optimizations, like loop fusion, in multi-threaded environment to achieve maximum performance.ContraThe memory model also leads to performance cost, because of locks and other communication stuff.
  • 9.
    History1991: Oak wasdeveloped under the name "The Green Project" by James Goslip and other developers within 18 months. The project was initiated by Sun Microsystems to develop a kernel for executing safe, portable, object-oriented and multi-threaded software on set-top boxes. 1995: Java 1.0 has been published by Sun Microsystems.
  • 10.
    History2004: The originalmemory model was updated through the Java Community Process, as Java Specification Request 133, for Java 5.0, because the old one prevented many runtime optimizations and it didn’t provide enough guarantees for code safety.
  • 11.
    Atomicity rulesAccesses tovariables of primitive types (excluding long and double) and reference variables are atomic.Accesses to volatile variables of primitive types (including long and double) and reference variables are atomic.Operations on atomic variables in the package „java.util.concurrent.atomic“ are atomic, too.
  • 12.
    Ordering rulesJMM definesan happens-before partially order for all instructions in a multi-threaded program.The order guarantees: Thread B will see the result of Thread A, if there exists a happens-before relation between B and A (because of corresponding visibility rules).If there exists a happens-before relation, the order of instructions will be reordered at will.
  • 13.
    Happens-before orderProgram orderruleMonitor lock ruleVolatile variable ruleThread start ruleThread termination ruleInterruption ruleFinalizer ruleTransitivity
  • 14.
    Visibility rulesThread ruleMonitorlock ruleVolatile variable ruleAtomic variable ruleFinal variable rule
  • 15.
    Piggybacking on synchronizationPiggybackingon synchronization means combining the program order rule with the monitor lock rule or volatile variable rule concerning ordering and visibility of ordering and visibility, appearing in a code sequence.Pro: Not every method must be synchronized. Performance benefitA global order can be asserted by using a volatile variable as a guard.
  • 16.
    PublicationThe absence ofa happens-before order between publishing a shared object and accessing it leads to a partially constructed object.@NotThreadSafepublic class UnsafeLazyInitialization{ private static Resource resource; public static Resource getInstance() {if (resource == null) resource = new Resource();return resource;}}
  • 17.
    Thread-safe lazy initilizationThread-safelazy initialization is guaranteed by synchronization of the getInstance method.@ThreadSafepublic class SafeLazyInitialization{ private static Resource resource; public synchronized static Resource getInstance() {if (resource == null) resource = new Resource();return resource;}}
  • 18.
    Double-checked lockingAntipattern (notthread safe), invented to reduce the impact of synchronization.In the original JMM synchronization was expensive concerning performance.Since JRE 5.0 it’s obsolete, because of a tuned JVM (especially JMM).Now it’s better to use thelazy initialization holder class idiom to gain performance, because it offers the same benefit and is easier to understand.
  • 19.
    Double-checked locking@NotThreadSafepublic classDoubleCheckedLocking{ private static Resource resource; public static Resource getInstance() {if (resource == null) { synchronized (doubleCheckedLocking.class) {if (resource == null) resource = new Resource();}}}}
  • 20.
    Lazy initialization holderclass idiomcombines the safe lazy initialization with the lazy initialization holder class idiomdoes not require synchronization, because of eager class initialization idiom@ThreadSafepublic class ResourceFactory{ private static class ResourceHolder{ public static Resource resource= new Resource();} public static Resource getResource() {return ResourceHolder.resource;}}
  • 21.
    Initialization safetyAllows properlyconstructed immutable objects to be safely shared across threads without synchronization.Threads, obtaining a reference to that objects, are guaranteed to see up-to-date values of final fields.Initial writes aren’t reordered with accesses, coming after the final field is frozen.
  • 22.
    ChangesAccesses to volatilevariables won’t be reordered with any other memory operation.useful for using a volatile variable as a guardstatic int a = 0, b = 0;static int x = 0, y = 0;static volatile boolean initialized =false; //Thread Aa = 1;b = 1;initialized =true; //ThreadBwhile(!initialized){}x = a;y = b;
  • 23.
    ChangesIntroduction of thehappens-before orderThe initialization of final fields will never be reordered with operations following the finalization associated with the end of the constructor. Final means final.
  • 24.
    Implementation sketchDependent onthe underlying hardware platform model , the Java compiler insert the right memory barriers/fences, so that the Java memory model is valid. In a general model, the following fences exist:LoadLoadStoreStoreLoadStoreStoreLoad
  • 25.
    Implementation sketchA synchronizedblock can be realized as follows:public class X { private int a,i; public void synchronized f(){LoadLoad;LoadStore;i= a; a =i;StoreLoad;StoreStore;}}
  • 26.
    Thank you foryour attention! Questions?