Poniżej fragment kodu jest z Efektywna Java 2nd Edition Blokada z podwójnym zatwierdzeniemCzy to jest lepsza wersja dokładnie sprawdzić Blokowanie bez narzutu lotnej i synchronizacji
// dwukrotnie sprawdzić idiom dla leniwej inicjalizacji instancji pola
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 z funkcją Double Checked Locking jest zmiana kolejności wewnątrz drugiego sprawdzania, tak aby inny wątek mógł zobaczyć wartości pola/wyniku, które mogą pozostać w trakcie wykonywania. Aby tego uniknąć, sprawiamy, że pole widzenia staje się zmienne, a widoczność i porządek są gwarantowane.
Ale można to osiągnąć przez poniższym kodzie również
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;
}
Więc po inicjalizacji, kiedy zostały zrobione, to nie wątek będzie musiał lotnych odczytu lub synchronizacji napowietrznych. Proszę Sprawdź, czy moje założenia są poprawne, czy nie?
Czy blokowanie z podwójną kontrolą nie jest obecnie uważane za coś złego? http://en.wikipedia.org/wiki/Double-checked_locking – Bathsheba
Jest jeden prosty sposób, aby tego uniknąć: zmień kod tak, aby _nie_ wymagał podwójnego sprawdzenia blokowania! W (100 - epsilon)% przypadków jest to wykonalne, i co należy zrobić w każdym razie. – fge