I need some memory model advice.
As we know volatile write
and subsequent volatile read
have happens-before relationships. Also we know that constructors are not synchronized and there is no hb between constructor returns and using fields initialization (except final fields). Now consider the following code:
public class MyClass{
public volatile String str1;
public volatile String str2;
public MyClass(String str1, String str2){
this.str1 = str1;
this.str2 = str2;
}
public void use(){
System.out.println(str1 + str2);
}
}
usage:
public volatile MyClass mc = null;
Thread(() -> {
mc = new MyClass("str1", "str2"));
}).start();
Thread(() -> {
If(mc != null)
mc.use; //Is it guaranteed that str1str2 will be printed if we get here?
}).start();
Is it guaranteed that if the thread discovers mc != null
then str1str2
will always be printed?
I think it is guaranteed by the JMM because here in mc = new MyClass("str1", "str2"));
writing to mc and writing to str1
and str2
are in happens-before relationship. This is because writing to str1
/str2
are performed according to inter-thread semantic so they are in program order. So we have writing to mc
hb reading mc
so "str1str2" will always be printed.
Also if we make fields str1
/str2
non-volatile there will be no such guarantee anymore.
Is my judgement correct? Can you please expand?