Will calling a setter after constructor execution but before returning the reference will be a safe publication ?
public class SafePublication {
private int i = 0;
private SafePublication() {
i = 10;
}
// Here we are calling setter are object creation.
//Will this change be visible to other threads
public static SafePublication getInstance() {
SafePublication pub = new SafePublication();
pub.setVal(20);
return pub;
}
private void setVal(int x) {
this.i = x;
}
}
No it won’t be safe.
The
setValmethod is not synchronized, andiis not volatile. Therefore, there will be no synchronization point between an update toi(viasetVal) and any code run on another thread that readsi. The fact that thesetValcall happens in the thread that constructs the instance makes on difference.The bottom line is that another thread may see the value of
ias any one of0,10or20.It is not. The problem is that the other thread may not see the correct value of
i.I think you are confusing this situation with the case where the field is
final. There, the JLS does specify that the field is safely published. The problem is that this guarantee does not apply to non-final fields; see JLS 17.5. The wording is as follows:(Emphasis added)
AFAIK, there is nothing in JLS 17.4 or JLS 17.5 that offers that guarantee. The only thing that is guaranteed is that nothing will see the value of
ibefore default initialization has taken place. (Please feel free to prove me wrong … with references to the JLS.)