2016-06-22 17 views
15

To jest metoda keySet() klasy HashMap z JDK. Dlaczego autor przypisał pole (keySet) do zmiennej lokalnej ks?przypisz pole instancji do zmiennej lokalnej

public Set<K> keySet() { 
    Set<K> ks; 
    return (ks = keySet) == null ? (keySet = new KeySet()) : ks; 
} 

Jaka jest różnica między powyższym a poniższym? Czy ma to coś wspólnego z bezpieczeństwem nici?

public Set<K> keySet() { 
    return (keySet == null ? (keySet = new KeySet()) : keySet; 
} 
+0

Może; chociaż wygląda na to, że próbuje ustawić zmienną na poziomie klasy, zapewniając, że zmienna nie jest pusta i zwraca tę wartość. Jednak nie mam o tym pojęcia. Musiałbym popatrzeć na całą klasę. –

+0

Być może dla jasności intencji – alphablue

+1

Może być uważany za duplikat http://stackoverflow.com/q/28975415/3182664 http://stackoverflow.com/q/2785964/3182664 http://stackoverflow.com/q/ 37776179/3182664 http://stackoverflow.com/q/32619269/3182664 i prawdopodobnie kilka innych ... – Marco13

Odpowiedz

6

rozszerzyć nieco na Odpowiedź Michaela, spodziewam się, że jest tam, aby zapewnić, że metoda keySet() nigdy nie zwróci null, być może oprócz zapewnienia korzyści wydajności zauważyć.

Biorąc pod uwagę ten kod:

public Set<K> keySet() { 
    return (keySet == null ? (keySet = new KeySet()) : keySet; 
} 

Byłoby przynajmniej teoretycznie możliwe w kodzie wielowątkowym, że pole keySet może być ustawiony na null pomiędzy pierwszym odczycie (keySet == null) i drugim czytać, gdzie go jest zwracany. Nie spojrzałem na resztę kodu, ale zakładam, że są inne miejsca, gdzie keySet jest potencjalnie przypisany null. Niezależnie od tego, czy dzieje się to w wyniku problemu obserwowanego w środowisku naturalnym, czy też środka obronnego, będzie to pytanie dla autorów.

Rzeczywisty kod:

public Set<K> keySet() { 
    Set<K> ks; 
    return (ks = keySet) == null ? (keySet = new KeySet()) : ks; 
} 

... nie ma tego problemu, ponieważ pole jest odczytywany tylko raz.

+0

Yup. Chodzi o to, aby być bezpiecznym w środowisku wielowątkowym. –

+0

@msandiford niekoniecznie gdzieś jest ustawiony na null, operacje mogą po prostu zostać ponownie uporządkowane, ponieważ istnieją dwie racy odczytu wspólnej zmiennej. – Eugene

8

Jeśli spojrzeć na zgłoszenia w abstract class AbstractMap<K,V>keySet, widać, że jest zdefiniowany jako:

transient volatile Set<K> keySet; 

Ponieważ jest niestabilna, czytając go tylko raz przy użyciu lokalnego zadanie zmienną jest tańsze niż czytanie go dwa razy, jak w innym podanym przykładzie.

Ponadto, jeśli były, aby powrócić bezpośrednio zmienną keySet, następnie cały kod klient będzie mieć do czynienia z lotnych odniesienia vs. nieulotnej odniesienia (tj Set<K> ks)

+2

Dzięki za odpowiedź na temat zmiennego pola odczytu, nie pomyślałem o tym. Czy mógłbyś wyjaśnić część "radzenia sobie z lotną referencją a nielotną referencją"? – joohwan

+1

Nie ma takiego pojęcia, jak "lotne odniesienie względem nielotnego odniesienia". – Boann

+0

@Boann To prawda. Dzięki. –

Powiązane problemy