Consider the "double-check idiom for lazy initialization of instance fields":
// Item 71 in Effective Java copied from this interview with Bloch. private volatile FieldType field; FieldType getField() { FieldType result = field; if (result == null) { // First check (no locking) synchronized(this) { result = field; if (result == null) // Second check (with locking) field = result = computeFieldValue(); } } return result; }
I want to be able to reset the field in a safe way (force it to load again from the database, in my case). I assume that we could do this by having a reset method:
void reset() { field = null; }
Is this the standard way of doing resetting the field? Is it safe? Any pitfalls? I'm asking because Bloch gave the following warning about double-checked lazy-loading: "The idiom is very fast but also complicated and delicate, so don't be tempted to modify it in any way. Just copy and paste -- normally not a good idea, but appropriate here."
Thanks in advance, Playa from the Himalayas.
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 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With