2012-11-21 13 views
5

W JCIP, sekcja 3.2.1 "Praktyki bezpiecznego konstruktora", istnieje ostrzeżenie przed wyciekaniem this do innego wątku od konstruktora, "nawet jeśli publikacja jest ostatnią instrukcją w konstruktorze." Ta ostatnia część wydaje mi się zbyt silna i nie ma żadnego uzasadnienia. Co się dzieje po budowie, której muszę unikać? Czy są wyjątki? Interesuje mnie, ponieważ niedawno przesłałem kod, w którym zrobiłem to coś, i chcę zdecydować, czy istnieje uzasadnienie, aby wrócić i refactor.java: dlaczego nie powinno się uciec przed konstruktorem?

+1

http://msmvps.com/blogs/jon_skeet/archive/2010/09/02/don-t-let-this-get-away.aspx – SLaks

Odpowiedz

4

Jeśli chodzi o model pamięci Java, wyjście konstruktora odgrywa rolę w ostatecznej semantyce pola, dlatego istnieje różnica, czy instrukcja jest przed lub po zakończeniu konstruktora.

This works       This doesn't work 
------------------------------------------------------------- 

static Foo shared;     static Foo shared; 

class Foo       class Foo 
{         { 
    final int i;      final int i; 
    Foo()        Foo() 
    {         { 
     i = 1;        i = 1; 
              shared = this; 
    }         } 
}         } 

shared = new Foo();    new Foo(); 

(Uwaga: shared nie jest lotna, publikacja jest przez rasy danych).

Jedyną różnicą między przykładami 2 przypisuje shared przed lub po wyjściu konstruktora. W drugim przykładzie, i=1 może zostać zmieniony po przypisaniu.

Jeśli publikacja jest zsynchronizowaną czynnością, np. przez zmienną lotną, to jest ok; inne wątki będą obserwowały w pełni zainicjowany obiekt; pola nie muszą nawet mieć final.

Publikacja za pośrednictwem wyścigu danych (lub robienia czegokolwiek przez wyścig danych) jest bardzo trudnym zadaniem, które wymaga bardzo ostrożnego uzasadnienia. Jeśli unikniesz wyścigu danych, sprawy są znacznie prostsze. Jeśli twój kod nie zawiera wyścigu danych, nie ma różnicy między wyciekiem this bezpośrednio przed zakończeniem konstruktora, a publikowaniem go zaraz po zakończeniu konstruktora.

4

Nigdy nie należy przeciekać this od konstruktora w jakimkolwiek punkcie, "nawet [...] w ostatnim zestawieniu." Ponieważ this nie jest w pełni skonstruowany, mogą się zdarzyć bardzo dziwne rzeczy. Zobacz this SO answer na bardzo podobne pytanie.

4

Nigdy nie należy przechodzić this z konstruktora (znanego jako „przecieka this”)

Jednym z powodów, że nie powinno to zrobić, nawet jeśli jest to ostatni wiersz konstruktora, jest to, że JVM jest dozwolone do ponownego zamawiania wyciągów, o ile nie ma to wpływu na efekt w bieżącym wątku. Jeśli this zostanie przekazany do procesu działającego w innym wątku, zmiana kolejności może spowodować dziwne i subtelne błędy.

Innym powodem jest to, że podklasy mogą zapewniać własną inicjalizację, więc konstrukcja może nie być kompletna na ostatnim wierszu konstruktora klasy.

Powiązane problemy