Java Memory Model (JMM) Flashcards
What does the JMM do? And why is it needed?
It defines a partial ordering on all actions of a program.
The JMM inserts memory barriers at appropriate places which ensures that’s correctly synchronised Java program runs correctly on all processor architectures.
What are all the happens-before rules of the JMM, and what does each do?
Program order rule: each action happens-before every action that comes later in the program
Volatile variable rule: a write to a volatile variable happens-before every subsequent read of that variable
Monitor lock rule: an unlock on a monitor lock happens-before every subsequent unlock
Thread start rule: a call to Thread.start happens-before all actions in that thread
Thread termination rule: any action in a thread happens-before that thread terminates
Interruption rule: a thread calling interrupt on another thread happens-before the interrupted thread detects the interrupt
Finaliser rule: the end of a constructor happens-before the start of the finaliser for that object
Transitivity: if A happens-before B and B happens-before C then A happens-before C
What is piggybacking on volatile?
It is when a write to a volatile variable is placed after a write to a shared variable(program order rule), therefore if another thread reads the volatile variable it must wait until after the both the shared and volatile variable has been written too. This “syncs” the 2 threads and ensures visibility of the shared variable. However ensuring visibility only means that there can still be race conditions.
How can final fields ensure thread safety? And how can this safety be undermined?
If a final variable is assigned in a constructor then any read of the variable of the object from a any thread will be able to see the up to date value of the variable. This is only if the object was constructed correctly. If a reference to the object was allowed to “escape” (assigning the object to a static variable in the constructor) in which any thread can see the the object before construction is complete -> final variable not guaranteed to have thread safety
How can static initialisers ensure thread safety? And what must be done to ensure thread safety in the lazy case?
Static initialisers are run by the JVM at class initialisation time, after class loading but before the class is used by any thread. Memory writes made during static initialisation are automatically visible to all threads. This only applies to the as-constructed state so if initialisation of a static variable is only called later by a thread then the synchronisation tag is needed for thread safety, whereas no synchronisation tag is needed if the static variable is initialised at initialisation time.