I was trying something crazy :p
Created a TestClass (following singleton design pattern) A main method which initialise the reflection for TestClass and starts two thread which creates TestClass new instance using reflections.
Below is the code
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class SingletonPattern {
public static void main(String[] args) throws InterruptedException, IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
final TestClass[] i1 = {null};
final TestClass[] i2 = {null};
final Constructor<TestClass> constructor = TestClass.class.getDeclaredConstructor();
constructor.setAccessible(true);
Thread t3 = new Thread() {
@Override
public void run() {
try {
i1[0] = constructor.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
}
};
Thread t4 = new Thread() {
@Override
public void run() {
try {
i2[0] = constructor.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
}
};
t3.start();
t4.start();
t3.join();
t4.join();
System.out.println((i1[0] == i2[0]) " " i2[0].equals(i1[0]));
}
static class TestClass implements Cloneable, Serializable{
private static TestClass instance;
private static final Object obj = new Object();
private TestClass() {
synchronized (TestClass.class) {
for (int i = 0; i < 100000; i ) ;
if (instance != null) {
throw new RuntimeException("Operation not allowed. Use getInstance method.");
}
}
}
public static TestClass getInstance() {
if (instance == null) {
synchronized (TestClass.class) {
if (instance == null) {
for (int i = 0; i < 100000; i ) ;
instance = new TestClass();
}
}
}
return instance;
}
public static TestClass getClone() {
try {
return (TestClass) instance.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return instance;
}
private Object readResolve() {
return getInstance();
}
}
}
Output which I am getting
false false
If the synchronized block in constructor are really getting synchronised then I should be seeing some exception. But that is not happening.
Can anyone explain why its happing like this? I am using Java version : corretto-1.8.0_282
CodePudding user response:
If the synchronized block in constructor are really getting synchronised then I should be seeing some exception. But that is not happening.
In your constructor
method, instance != null
will always return false because instace
is never assigned.
You can add instance = this
, in this case, only one thread can construct an instance through reflection, and the others will get a exception:
private TestClass() {
synchronized (TestClass.class) {
for (int i = 0; i < 100000; i ) ;
if (instance != null) {
throw new RuntimeException("Operation not allowed. Use getInstance method.");
}
instance = this;
}
}