Domanda

Devo rendere sicuro un thread ArrayList di ArrayLists.Inoltre, non posso consentire al cliente di apportare modifiche alla raccolta.Il wrapper non modificabile lo renderà sicuro per i thread o ho bisogno di due wrapper nella raccolta?

È stato utile?

Soluzione

Dipende.Il wrapper impedirà solo le modifiche alla raccolta che racchiude, non agli oggetti nella raccolta.Se disponi di un ArrayList di ArrayList, l'elenco globale e ciascuno dei suoi elenchi di elementi devono essere racchiusi separatamente e potresti anche dover fare qualcosa per il contenuto di tali elenchi.Infine, devi assicurarti che gli oggetti dell'elenco originale non vengano modificati, poiché il wrapper impedisce solo le modifiche attraverso il riferimento al wrapper, non all'oggetto originale.

In questo caso NON è necessario il wrapper sincronizzato.

Altri suggerimenti

Su un argomento correlato: ho visto diverse risposte che suggeriscono l'utilizzo della raccolta sincronizzata per ottenere la sicurezza del thread.L'uso della versione sincronizzata di una raccolta non la rende "thread-safe" - sebbene ogni operazione (inserimento, conteggio ecc.) sia protetta da mutex quando si combinano due operazioni non vi è alcuna garanzia che vengano eseguite in modo atomico.Ad esempio il seguente codice non è thread-safe (anche con una coda sincronizzata):

if(queue.Count > 0)
{
   queue.Add(...);
}

Il wrapper non modificabile impedisce solo modifiche alla struttura dell'elenco a cui si applica.Se questo elenco contiene altri elenchi e sono presenti thread che tentano di modificare questi elenchi nidificati, non sei protetto dai rischi di modifiche simultanee.

Osservando l'origine delle raccolte, sembra che non sia modificabile non renderlo sincronizzato.

static class UnmodifiableSet<E> extends UnmodifiableCollection<E>
                 implements Set<E>, Serializable;

static class UnmodifiableCollection<E> implements Collection<E>, Serializable;

i wrapper delle classi sincronizzate contengono un oggetto mutex per eseguire le parti sincronizzate, quindi sembra che sia necessario utilizzarli entrambi per ottenerli entrambi.Oppure lancia il tuo!

Credo che, poiché il wrapper UnmodifyingList memorizza l'ArrayList in un campo finale, qualsiasi metodo di lettura sul wrapper vedrà l'elenco com'era quando il wrapper è stato costruito purché l'elenco non venga modificato dopo la creazione del wrapper e come purché gli ArrayList mutabili all'interno del wrapper non vengano modificati (da cui il wrapper non può proteggersi).

Sarà thread-safe se la vista immodificabile viene pubblicata in modo sicuro e l'originale modificabile non viene mai modificato (inclusi tutti gli oggetti contenuti ricorsivamente nella raccolta!) dopo la pubblicazione della vista immodificabile.

Se vuoi continuare a modificare l'originale, puoi creare una copia difensiva dell'oggetto grafico della tua raccolta e restituirne una visualizzazione immodificabile, oppure utilizzare un elenco intrinsecamente thread-safe per cominciare e restituire una visualizzazione immodificabile di Quello.

Voi non può restituisce una Lista immodificabile (lista sincronizzata (la Lista)) se intendi comunque accedere alla Lista non sincronizzata in seguito;se lo stato mutabile è condiviso tra più thread, allora Tutto i thread devono essere sincronizzati su Stesso si blocca quando accedono a quello stato.

Un oggetto immutabile è per definizione thread-safe (assumendo che nessuno conservi i riferimenti alle raccolte originali), quindi la sincronizzazione è non necessario.

Avvolgimento della lista di array esterni usando raccolte.unmodifiablelist () impedisce al client di cambiare il suo contenuto (e quindi lo rende sicuro di thread), ma le liste di array interne sono ancora mutabili.

Avvolgimento delle elist di array interni usando raccolta.unmodifiablelist () impedisce al cliente di cambiare il loro contenuto (e quindi li rende al sicuro), che è ciò di cui hai bisogno.

Facci sapere se questa soluzione causa problemi (overhead, utilizzo della memoria, ecc.);altre soluzioni potrebbero essere applicabili al tuo problema.:)

MODIFICARE:Naturalmente, se le liste vengono modificate NON sono thread-safe.Supponevo che non dovessero essere apportate ulteriori modifiche.

Non sono sicuro di aver capito cosa stai cercando di fare, ma direi che nella maggior parte dei casi la risposta è "No".

Se imposti un ArrayList di ArrayList ed entrambi, gli elenchi esterno ed interno non potranno mai essere modificati dopo la creazione (e durante la creazione solo un thread avrà accesso agli elenchi interno ed esterno), probabilmente sono thread-safe da un wrapper (se entrambi , gli elenchi esterni ed interni sono racchiusi in modo tale che sia impossibile modificarli).Tutte le operazioni di sola lettura sugli ArrayList sono molto probabilmente thread-safe.Tuttavia, Sun no garanzia siano thread-safe (anche non per operazioni di sola lettura), quindi anche se potrebbe funzionare adesso, potrebbe rompersi in futuro (se Sun crea una cache interna dei dati per un accesso più rapido, ad esempio).

Ciò è necessario se:

  1. C'è ancora un riferimento all'elenco modificabile originale.
  2. È possibile che l'accesso all'elenco venga effettuato tramite un iteratore.

Se intendi leggere dall'ArrayList solo in base all'indice, potresti supporre che sia thread-safe.

In caso di dubbio, scegli il wrapper sincronizzato.

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