On 7/25/17 3:37 PM, Sergey Bylokhov wrote:
If that is the case then I think we have a few places where we do this "manual conditional synchronization" that should probably be investigated. If I remember correctly, though, they may use the following paradigm which might not suffer from that issue:

Does it help if a local variable is used, as in:

GE env = this.localEnv
if (env == null) {
     synchronized (class) {
         if (this.localEnv == null) {
             localEnv = createGE();
         }
         env = this.localEnv;
     }
}
return env;

This ensures that the second read from the field is done in the synchronized block for the case that it was originally found to be null, though this might not help if the line "localEnv = createGE()" can reorder code from inside the call to createGE() to code outside of it. However those dangling reordered stores should be resolved before it leaves the synchronized block, no?

I think that it is possible that one thread will do:
  - create an object
  - assign the object to the localEnv.
  - Initialize the object.
And the second thread will do:
  - Read non-null value from the this.localEnv to the env
  - Check env to null
  - Return non-initialized object.

I can see that. I suppose one thing that keeps this from causing problems in AWT is that we tend to be single-threaded for most applications. I suppose that one could get even more sophisticated to prevent that case, but in the end, as I said, I can see the simplicity of using the inner class now in getting all of this right.

I'll do a search and see if there are any cases of the above paradigm left...

                        ...jim

Reply via email to