Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is this a better version of Double Check Locking without volatile and synchronization overhead

Below code snippet is from Effective Java 2nd Edition Double Checked Locking

// Double-check idiom for lazy initialization of instance fields

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;
}

From what i know the main Problem with Double Checked Locking is the reordering inside second check locking so that the other thread might see the values of field/result as set which may be infact still be in executing. To avoid this we make the reference of field as volatile to gurantee visibility and reordering.

But this can be achieved by the below code also

private FieldType field; // non volatile
private volatile boolean fence = false;

FieldType getField() {
    if (field == null) {  // First check (no locking) // no volatile read
        synchronized(this) {   //  inside synch block no problem of visibilty will latest           //value  of field 
            if (field == null) {// Second check (with locking)  
                Object obj =  computeFieldValue();
             fence = true; // any volatile write will take. this will make sure statements are //not reorder with setting field as non null.
            field = (FieldType)obj; // this will be only set after computeFieldValue has been //completed fully
           }
        }
    }
    return field;
}

So after when the initialization have been done, then no thread will have to for volatile read or synchronization overhead. Please see if my assumptions are right or not?

like image 229
veritas Avatar asked Jun 18 '13 12:06

veritas


1 Answers

The JLS (Section 17.4.5) states:

"A write to a volatile field (§8.3.1.4) happens-before every subsequent read of that field."

You are not reading the fence variable after it is updated, so there is no "happens-before" relationship between the thread that updates fence and any second thread. That means that the second thread is not guaranteed to see the updates to the field variable made by the first thread.

In short, your "improved" code is a broken implementation of double-checked locking.

like image 50
Stephen C Avatar answered Sep 24 '22 20:09

Stephen C