Question

I'm new to the Java threading and have only recently started to read up on the Memory Model. From my understanding the Java Memory Model as it stands allows the compiler to make optimizations.

This can complicate multi-threaded code and synchronization but my question is for something much simpler. Take this example since the two statements are not dependent on each other, is it possible that the compiler could change the ordering of the code in the try statement and therefore break the check?

boolean success = false;
try{
 MyClass.someFunction();
 success = true;
}
catch(Exception e){

}

if(success){    
    System.out.println("Sucess!");
}
else{
    System.out.println("Fail!");
}
Was it helpful?

Solution

As Java cannot understand what MyClass.someFunction() does, it cannot safely reorder this statement. In fact, most data dependency checkers are completely incapable of moving outside of a function boundary due to side-effects.

Threads are a special case, and not unique to Java - data ends up in registers, and won't be refetched from memory unless needed. Java's solution is the transient keyword (similar to volatile in other languages).

OTHER TIPS

No. The Java compiler is required to do what you'd expect -- print Success! if Myclass.someFunction() returns normally and Fail! if it raises an exception. This comes from the semantics of Java in general, and is independent of any compiler optimizations your compiler might make (except insofar as it might constrain what optimizations are legal).

The reason is that the Java language specification says that within a single thread, the program must behave exactly as though statements were executed in order, top to bottom. The compiler is free to rewrite your program in all kinds of unintuitive ways in order to generate bytecode, but it must preserve the illusion that within a single thread, it's running exactly the statements you typed in your source code, in the correct order.

The Java language specification could extend that to multi-threaded contexts as well, and say that every thread must always see a state of the world consistent with all of your threads executing exactly the source code you typed in. However, (a) that would make it very difficult to write a correct compiler optimization, and many otherwise useful optimizations would be illegal; and (b) it wouldn't help programmers very much since it wouldn't eliminate the need for proper synchronization anyway; it'd mostly just turn broken programs into less-obviously broken programs.

Instead, the Java memory model defines precise rules for when memory modifications in one thread are visible to other threads, and lets the compiler do what it wants otherwise. This is a good compromise, since it gives programmers a set of rules they can use to make sure their multithreaded programs are correct while still giving compiler writers leeway to implement good optimizations.

But the important point for your question is: the compiler can do whatever it wants behind the scenes, but it's not allowed to change the meaning of your program. In a single-threaded context, the meaning of your program is well defined and would not permit the compiler to do the bad things you were thinking it could do.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top