Happens before rule

  • For a lock, all ops before lock releases happens before ops after lock is acquired
  • All volatile writes and before its writes happens after reads and ops after that read
  • Thread start and ops before that start happnes before things within that start
  1. Volatile forces the program to write the value immediately to the memory in an atomic action by passing cpu cache. reading bypasses CPU cache too, or force the CPU cache to expire early
  2. This means if we have only one writer, and all reader/writers are volatile, then the program is thread safe. However, it is not true if you have more than one writer
  3. Visibility rule: if the thread reads a volatile value, then ALL variables visible to the thread will be re-read from the memory. This means the order of instructions matter! If you have read AFTER the volatile read, or it got reordered by the compiler, than the vars after the volatile is NOT affected. Luckily, JVM prevents this
  4. Note ++ is a syntactic sugar, it is compiled into a read-update-write operation - so you can’t use volatile with it!

Java singleton with volatile


public class Singleton {

private voltile Singleton _instance;

private Singleton() {
}

private Singleton getInstance() {

	if (_instance == null) {
		synchronized(Singleton.class) {
			if(_instance == null)
			  _instance = new Singleton();
		}
	}

	return _instance
}

}

Note that without this volatile the code is incorrect

  • Compiler might reorder the so that _instance is assigned the memory address before the instance finishes init
  • This means the another thread may get an object with only defaults

static

class King{

private static King kingInstance;
static {
	kingInstance = new King();
}

private King(){
}

public statiic King getKingInstance() {
	return kingInstance;
}
}



class King{
private static final King kingInstance = new King()

static King getInstance() {
	return kingInstance;
}

private King(){
}

}

Lazy loading with internal static class

public class King {

private King(){

}

private static class KingInstance {
	private static final King KINGINSTNACE = new King();
}

public static King getInstance(){
	return KingInstance.KINGINSTANCE;
}

}

  • static interanal type will not be instantiated immediately at class loading time, and only be instantiated at the first call of getInstance()
  • JVM’s class loading is thread safe, so only class is loaded