Frage

Ich fülle eine Sammlung ein einziges Mal, als mein J2EE Webapp beginnt. Dann mehrere Gewinde es zur gleichen Zeit zugreifen können, aber nur, es zu lesen.

Ich weiß, unter Verwendung einer synchronisierten Sammlung obligatorisch ist für Parallelen zu schreiben, aber ich brauche es noch Parallelen lesen?

War es hilfreich?

Lösung

Normalerweise nein, weil Sie ändern nicht den internen Zustand der Sammlung in diesem Fall. Wenn Sie über die Auflistung durchlaufen eine neue Instanz des Iterator erstellt wird und der Zustand der Iteration pro Iterator-Instanz.


Abgesehen beachten Sie: Denken Sie daran, dass eine Nur-Lese-Sammlung, indem Sie nur verhindern Änderungen an der Sammlung selbst. Jedes Sammelelement ist noch veränderbar.

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

}

Diese Ausgänge:

5
5

Wichtige Überlegungen von @WMR answser.

  

Es hängt davon ab, ob die Fäden, die   Ihre Sammlung zu lesen gestartet   vor oder nachdem Sie es sind zu füllen. Wenn   sie begann, bevor Sie es zu füllen,   Sie haben keine Garantien (ohne   Synchronisieren), dass diese Fäden   jemals die aktualisierten Werte sehen.

     

Der Grund hierfür ist die Java Memory   Modell, wenn Sie wissen wollen, lesen Sie mehr die   Abschnitt „Sichtbarkeit“ unter diesem Link:    http://gee.cs.oswego.edu/dl/cpj/jmm. html

     

Und selbst wenn die Fäden gestartet   nachdem Sie Ihre Sammlung füllen, Sie   Möglicherweise müssen synchronisiert werden, weil Ihr   Sammlung Umsetzung könnte sich ändern   sein interner Zustand sogar auf Lese   Operationen (Danke Michael   Bar-Sinai ,   Ich wusste nicht, solche Sammlungen   existierte).

     

Eine weitere sehr interessante Lektüre auf dem   Thema der Parallelität, die umfasst   Themen wie Veröffentlichung von Objekten,   Sichtbarkeit usw. viel detaillierter   Brian Goetz ist Buch Java rel="nofollow   Concurrency in   Praxis .

Andere Tipps

Es hängt davon ab, ob die Fäden, die Ihre Sammlung liest gerade gestartet werden, bevor oder nachdem Sie es sind zu füllen. Wenn sie gestartet sind, bevor Sie es füllen, haben Sie keine Garantie (ohne Synchronisation), dass diese Fäden werden immer die aktualisierten Werte sehen.

Der Grund hierfür ist das Java-Speichermodell, wenn Sie mehr wissen wollen unter diesem Link im Abschnitt „Sichtbarkeit“ lesen: http://gee.cs.oswego.edu/dl/cpj/jmm.html

Und selbst wenn die Fäden, nachdem Sie füllen Sie Ihre Sammlung begonnen werden, könnten Sie müssen synchronisiert werden, da Ihre Sammlung Implementierung seinen internen Zustand auch auf Leseoperationen verändern könnte (durch Michael Bar-Sinai , ich nicht solche Sammlungen wusste gab es in dem Standard-JDK).

Eine weitere sehr interessante Lektüre zum Thema Gleichzeitigkeit, die Themen wie Veröffentlichung von Objekten umfasst, Sichtbarkeit usw. viel detaillierter ist Brian Goetz Buch Java Concurrency in Practice .

Im allgemeinen Fall, sollten Sie. Dies liegt daran, einige Sammlungen ihre interne Struktur ändern während liest. Ein LinkedHashMap, die den Zugriff verwendet, um ein gutes Beispiel. Aber nicht nur mein Wort für es:

  

Zugriff geordneten verknüpften Hash-Karten, nur die Karte mit get Abfrage ist eine strukturelle Modifikation    Die verlinkte Hash-Karte javadoc

Wenn Sie absolut sicher sind, dass es keine Caches, keine Sammlung Statistiken, keine Optimierungen, kein lustiges Zeug überhaupt - Sie müssen nicht synchronisiert werden müssen. In diesem Fall würde ich eine Art Einschränkung für die Sammlung zu setzen haben: Sie erklären nicht die Sammlung als Karte (die LinkedHashMap erlauben würde), sondern als HashMap (für die Puristen, eine endgültige Unterklasse von HashMap, aber das könnte es zu nehmen weit ...).

Sie müssen nicht, wie in anderen Antworten erklärt. Wenn Sie sicherstellen möchten, dass Ihre Sammlung nur gelesen wird, können Sie:

yourCollection = Collections.unmodifableCollection(yourCollection);

(ähnliches Verfahren existiert für List, Set, Karten und andere Sammlungstypen)

Die Sammlung selbst nicht, aber denken Sie daran, dass wenn das, was hält es auch nicht unveränderlich ist, diese separaten Klassen ihre eigene Synchronisation benötigen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top