Domanda

Riempo una raccolta una sola volta all'avvio della mia webapp J2EE. Quindi, diversi thread possono accedervi contemporaneamente ma solo per leggerlo.

So che l'utilizzo di una raccolta sincronizzata è obbligatorio per la scrittura in parallelo, ma ne ho ancora bisogno per la lettura in parallelo?

È stato utile?

Soluzione

Normalmente no perché in questo caso non si modifica lo stato interno della raccolta. Quando si esegue l'iterazione sulla raccolta, viene creata una nuova istanza dell'iteratore e lo stato dell'iterazione è per istanza dell'iteratore.


Nota a parte: ricorda che mantenendo una raccolta di sola lettura si impediscono solo modifiche alla raccolta stessa. Ogni elemento di raccolta è ancora modificabile.

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

}

Questo output:

5
5

Considerazioni importanti da @WMR Answerer.

  

Dipende se i thread sono   la lettura della tua collezione è iniziata   prima o dopo averlo riempito. Se   sono iniziati prima di riempirlo,   non hai garanzie (senza   sincronizzazione), che questi thread   vedrà mai i valori aggiornati.

     

Il motivo è la memoria Java   Modella, se vuoi saperne di più leggi il   sezione " Visibilità " a questo link:    http://gee.cs.oswego.edu/dl/cpj/jmm. html

     

E anche se i thread sono stati avviati   dopo aver riempito la tua collezione, tu   potrebbe essere necessario sincronizzare perché il tuo   l'implementazione della raccolta potrebbe cambiare   il suo stato interno anche a lettura   operazioni (grazie Michael   Bar-Sinai ,   Non conoscevo tali raccolte   esistito).

     

Un'altra lettura molto interessante sul   argomento di concorrenza che copre   argomenti come la pubblicazione di oggetti,   visibilità, ecc. in modo molto più dettagliato   è il libro di Brian Goetz Java   Concorrenza in   Pratica .

Altri suggerimenti

Dipende se i thread che stanno leggendo la tua raccolta sono iniziati prima o dopo averla riempita. Se vengono avviati prima di compilarlo, non hai garanzie (senza sincronizzazione), che questi thread vedranno mai i valori aggiornati.

La ragione di ciò è il modello di memoria Java, se vuoi saperne di più leggi la sezione "Visibilità". a questo link: http://gee.cs.oswego.edu/dl/ cpj / jmm.html

E anche se i thread vengono avviati dopo aver riempito la tua raccolta, potresti dover eseguire la sincronizzazione perché l'implementazione della raccolta potrebbe cambiare il suo stato interno anche nelle operazioni di lettura (grazie Michael Bar-Sinai , non conoscevo tali raccolte esisteva nel JDK standard).

Un'altra lettura molto interessante sull'argomento della concorrenza che tratta argomenti come la pubblicazione di oggetti, la visibilità, ecc. in modo molto più dettagliato è il libro di Brian Goetz Java Concurrency in Practice .

Nel caso generale, dovresti. Questo perché alcune raccolte cambiano la loro struttura interna durante le letture. Un LinkedHashMap che utilizza l'ordine di accesso è un buon esempio. Ma non limitarti a crederci sulla parola:

  

Nelle mappe hash collegate ordinate per accesso, la semplice query della mappa con get è una modifica strutturale    Il javadoc della mappa hash collegata

Se sei assolutamente sicuro che non ci siano cache, statistiche di raccolta, ottimizzazioni o cose divertenti, non è necessario sincronizzarle. In quel caso avrei aggiunto un vincolo di tipo alla raccolta: non dichiarare la raccolta come una Mappa (che consentirebbe LinkedHashMap) ma come HashMap (per i puristi, una sottoclasse finale di HashMap, ma potrebbe anche prenderla lontano ...).

Non è necessario, come spiegato in altre risposte. Se vuoi assicurarti che la tua raccolta sia di sola lettura, puoi usare:

yourCollection = Collections.unmodifableCollection(yourCollection);

(esiste un metodo simile per Elenco, Set, Mappa e altri tipi di raccolta)

La collezione stessa non lo fa, ma tieni presente che se ciò che contiene non è immutabile, quelle classi separate hanno bisogno della loro sincronizzazione.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top