Czy jest to lepsza wersja Double Check Locking bez niestabilności i narzutu synchronizacji

Poniżej fragment kodu z efektywnej Java 2nd Edition Double Checked Locking

// Podwójne sprawdzenie idiomu dla leniwej inicjalizacji pól instancji

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

Z tego, co wiem, głównym problemem związanym z podwójnym sprawdzaniem blokowania jest zmiana kolejności wewnątrz drugiego blokowania kontroli, tak aby drugi wątek mógł zobaczyć wartości pola / wyniku jako zestawu, który może być faktycznie wykonywany. Aby tego uniknąć, odwołujemy się do pola jako zmiennego w celu zapewnienia widoczności i zmiany kolejności.

Ale można to osiągnąć również za pomocą poniższego kodu

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

Tak więc po zakończeniu inicjalizacji żaden wątek nie będzie musiał odnosić się do odczytu zmiennego lub narzutu synchronizacji. Sprawdź, czy moje założenia są słuszne, czy nie?

questionAnswers(3)

yourAnswerToTheQuestion