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.
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();
}
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.
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.