+3  A: 

I think this should be safe, but only because you're storing the field in a local variable. After this is done, there's no way for the local variable reference to magically change to null, even if another thread is resetting field's value half-way through.

InverseFalcon
I was just discussing that with my colleague ... we agreed ...
LES2
A: 

It seems like this will work as long as the reset method is the reset() method listed above. However, if the reset() method instantiates a new Object (like below), couldn't you end up potentially returning something different than you intended?

void reset() {
    field = new FieldType();
}
jacobko
yes, but that type of reset would defeat the whole purpose of the double-check idiom.
LES2
+3  A: 

Yes, this is thread safe.

The synchronized block is to prevent multiple threads from unnecessarily calling computeFieldValue(). Since field is volatile, the accesses in reset and getField are all well-ordered.

If the first check is non-null, getField is done; result is returned.

Otherwise, a lock is acquired, excluding any other thread that might set the field to non-null, but permitting any thread to set field to null. If any thread does set field to null, nothing should have changed; that's the condition that got the thread into the synchronized block. If another thread had already acquired the lock after the current thread's check, and set the field to a non-null value, the second check will detect that.

erickson
A: 

I guess it depends on exactly what you mean by thread-safe.

You could end up with a situation where a first instance is used after a second. That may be okay, or it may not.

Tom Hawtin - tackline