2008-09-30 11 views

Odpowiedz

19

Zwykle nie, ponieważ w tym przypadku nie zmieniasz stanu wewnętrznego kolekcji. Podczas iteracji nad kolekcją tworzona jest nowa instancja iteratora, a stan iteracji to instancja iteratora.


Poza Uwaga: Pamiętaj, że przez utrzymywanie tylko do odczytu kolekcja jesteś zapobieganiu tylko modyfikacje samej kolekcji. Każdy element kolekcji jest wciąż zmienny.

class Test { 
    public Test(final int a, final int b) { 
     this.a = a; 
     this.b = b; 
    } 

    public int a; 
    public int b; 
} 

public class Main { 

    public static void main(String[] args) throws Exception { 
     List<Test> values = new ArrayList<Test>(2); 
     values.add(new Test(1, 2)); 
     values.add(new Test(3, 4)); 

     List<Test> readOnly = Collections.unmodifiableList(values); 
     for (Test t : readOnly) { 
      t.a = 5; 
     } 

     for (Test t : values) { 
      System.out.println(t.a); 
     } 
    } 

} 

This wyjścia:

5 
5 

Ważne względy z @WMR answser.

To zależy od tego, czy wątków, które są czytanie kolekcji są uruchamiane przed lub po ty wypełnienie go. Jeśli zostaną uruchomione przed ich wypełnieniem, nie masz żadnych gwarancji (bez synchronizacji ), że te wątki kiedykolwiek zobaczą zaktualizowane wartości.

Powodem tego jest Java Pamięć modelu, jeśli chcesz wiedzieć więcej czytaj sekcję „widoczność” pod tym linkiem: http://gee.cs.oswego.edu/dl/cpj/jmm.html

I nawet jeśli gwinty są uruchamiane po wypełnieniu swojej kolekcji , ty może mieć do synchronizacji, ponieważ realizacja kolekcja może zmienić jego stan wewnętrzny nawet czytać operacji (dzięki Michael Bar-Sinai, nie wiedziałem takie zbiory istniał).

Kolejny bardzo interesujący odczyt na temat współbieżności która obejmuje tematy jak publikowania obiektów, widoczności itp bardziej szczegółowo jest książka Briana Goetz za Java Concurrency in Practice.

+0

Ta odpowiedź nie jest błędna, ale również niewystarczająca. Odpowiedź z @WMR ma kilka dodatkowych ważnych zastrzeżeń. W szczególności należy wziąć pod uwagę kwestię upewnienia się, że wątki czytnika będą rzeczywiście wyświetlać wartości zapisane przy uruchomieniu poprzez bezpieczną publikację lub jakąś barierę pamięci. –

+0

Zobacz @ WMR i moje odpowiedzi poniżej ... ta odpowiedź jest błędna, ponieważ() Działania mogą przekształcić stan wewnętrzny w kolekcjach (np. pamięci podręczne, ostatnio pobrane statystyki itp.). –

+0

@Alex Miller: Myślę, że odpowiedź jest nie tylko niewystarczająca, ale wyraźnie mówi "nie" bez wymieniania jakichkolwiek warunków dla tego nie. I to jest złe (i jak pewnie wiesz, niebezpieczne, jeśli na nim polegasz). – WMR

0

Sama kolekcja nie ma, ale należy pamiętać, że jeśli to, co zawiera, również nie jest niezmienne, te oddzielne klasy wymagają własnej synchronizacji.

+0

Wow, thx. Dobra robota – mattlant

3

Nie musisz, jak wyjaśniono w innych odpowiedziach.Jeśli chcesz mieć pewność, że Twoja kolekcja jest tylko do odczytu, można użyć:

yourCollection = Collections.unmodifableCollection(yourCollection); 

(podobna metoda istnieją List, Set, mapa i inne rodzaje kolekcji)

10

To zależy od tego, czy nici, które są czytanie kolekcji rozpoczyna się przed lub po jej wypełnieniu. Jeśli są uruchomione przed wypełnieniem, nie masz żadnych gwarancji (bez synchronizacji), że te wątki zobaczą zaktualizowane wartości.

Powodem tego jest Java pamięci model, jeśli chcesz wiedzieć więcej czytaj sekcję „widoczność” pod tym linkiem: http://gee.cs.oswego.edu/dl/cpj/jmm.html

I nawet jeśli gwinty są uruchamiane po wypełnieniu swojej kolekcji, to może mieć do synchronizacji, ponieważ twoja implementacja kolekcji może zmienić jej wewnętrzny stan nawet podczas operacji odczytu (dzięki Michael Bar-Sinai, nie wiedziałem, że takie kolekcje istnieją w standardowym JDK).

Kolejną bardzo interesującą lekturą na temat współbieżności, obejmującą takie tematy jak publikowanie obiektów, widoczność itp., Jest bardziej szczegółowo książka Briana Goetza: Java Concurrency in Practice.

+0

Dziękuję za tę odpowiedź, ale czy użycie "lotnych" pomoże uzyskać najnowsze wartości w innych wątkach? – SlowAndSteady

9

W ogólnym przypadku powinieneś. Dzieje się tak, ponieważ niektóre kolekcje zmieniają swoją wewnętrzną strukturę podczas czytania. A LinkedHashMap, która używa zlecenia dostępu, jest dobrym przykładem. Ale nie tylko wziąć na to moje słowo:

w dostępie zamówić połączonych map hash, jedynie zapytań mapę z GET jest modyfikacją konstrukcyjną The Linked hash map's javadoc

Jeśli jesteś absolutnie pewien, że istnieje nie są pamięciami podręcznymi, brakiem statystyk kolekcji, optymalizacją, zabawnymi rzeczami - nie trzeba synchronizować. W takim przypadku nałożyłbym ograniczenie typu na kolekcję: Nie zadeklaruj kolekcji jako mapy (która umożliwiłaby LinkedHashMap), ale jako HashMap (dla purystów, końcowa podklasa HashMap, ale to może również brać ją daleko...).

+0

Interesujące .. nigdy nie wiedziałem, że niektóre kolekcje zmieniają swoją wewnętrzną strukturę podczas czytania. – Jimmy

Powiązane problemy