Notes: I know that before java 5(given in 2004), double checking lock will fail in java, even you add "volatile" to the "instance" field. and after java 5 the volatile semantics has been right for double checking lock. I also know that without "volatile", double checking lock will fail even after java5, due to out-of-order executing. BUT, My question is : how to write codes to prove that(double checking lock will fail without "volatile")???
I have read lots of articles saying that double checking lock will fail in java, so I think below codes, which try to get a singleton instance of SocketFactory, will fail ( since the "instance" field is not volatile):
private static SocketFactory instance = null;
private static SocketFactory getInstance() {
if (instance == null) {
synchronized (SocketFactory.class){
if (instance == null){
instance = new SocketFactory(); // line 1
}
}
}
return instance;
}
but, the question is , if above code will fail, how can I prove that? I tried to write below codes( I thought, if the line 1 will be re-ordered, the "instance" reference may pointing to a SocketFactory object with the "constructed" field being "false"):
import java.io.*;
import java.nio.*;
import java.nio.file.*;
public class TIJ_doubleCheckingLock {
static TIJ_doubleCheckingLock instance;
private Object lock;
private boolean constructed = false;
{
constructed = false;
}
private TIJ_doubleCheckingLock() {
try{
Thread.sleep(10000);
} catch(Exception e) {
}
constructed = true;
}
static TIJ_doubleCheckingLock getInstance() {
if (instance == null) {
synchronized (TIJ_doubleCheckingLock.class) {
try{
Thread.sleep(1000);
} catch(Exception e) {
}
if(instance == null) {
instance = new TIJ_doubleCheckingLock();
}
}
}
return instance;
}
public static void main(String args[]) {
class MyThread extends Thread {
@Override
public void run() {
TIJ_doubleCheckingLock instance = TIJ_doubleCheckingLock.getInstance();
String fileName = "TIJ_doubleCheckingLockResult.txt";
java.io.File file = new File(fileName);
try {
if(!instance.constructed) {
java.nio.file.Files.write(Paths.get(file.toURI()), (instance.constructed+"").
getBytes("utf-8"), StandardOpenOption.CREATE, StandardOpenOption.APPEND);
}
} catch (Exception e) {
}
}
}
Thread firstThread = new MyThread();
firstThread.start();
try{
Thread.sleep(5000);
} catch(Exception e) {}
for(int i=0;i<10;i++) {
Thread thread = new MyThread();
thread.start();
}
}
}
but I never see a "false" in the txt file. so how can I prove that the double checking lock will fail?
Double checked locking was broken in Java. Your code works fine with Java 5 and onwards. The JVM since got a new memory model.
Also your code needs the volatile
keyword.
private static volatile SocketFactory instance;