Qual è la differenza tra ConcurrentHashMap e Collections.synchronizedMap (Mappa)?


607

Ho una mappa che deve essere modificata da più thread contemporaneamente.

Sembra che ci siano tre diverse implementazioni di Map sincronizzate nell'API Java:

  • Hashtable
  • Collections.synchronizedMap(Map)
  • ConcurrentHashMap

Da quello che ho capito, Hashtableè una vecchia implementazione (che estende la Dictionaryclasse obsoleta ), che è stata adattata in seguito per adattarsi Mapall'interfaccia. Mentre è sincronizzato, sembra avere seri problemi di scalabilità ed è scoraggiato per nuovi progetti.

E gli altri due? Quali sono le differenze tra Maps restituite da Collections.synchronizedMap(Map)e ConcurrentHashMaps? Quale si adatta a quale situazione?


7
@SmilesinaJar Il collegamento è attualmente interrotto, ecco una copia archiviata di questo articolo: Perché ConcurrentHashMap è meglio di Hashtable e altrettanto buono di un HashMap
informatik01

2
IBM: Come ConcurrentHashMap offre una maggiore concorrenza senza compromettere la sicurezza dei thread @ ibm.com/developerworks/java/library/j-jtp08223/…
pramodc84

Cordiali saluti, Java 6 ha portato ConcurrentSkipListMapcome un'altra Mapimplementazione thread-safe . Progettato per essere altamente concorrente sotto carico, utilizzando l' algoritmo Skip List .
Basil Bourque,

Risposte:


423

Per le tue esigenze, usa ConcurrentHashMap. Consente la modifica simultanea della mappa da più thread senza la necessità di bloccarli. Collections.synchronizedMap(map)crea una Mappa di blocco che peggiorerà le prestazioni, sebbene garantisca coerenza (se utilizzata correttamente).

Utilizzare la seconda opzione se è necessario garantire la coerenza dei dati e ogni thread deve disporre di una vista aggiornata della mappa. Usa il primo se le prestazioni sono critiche e ogni thread inserisce solo dati nella mappa, con letture che si verificano meno frequentemente.


8
Guardando il codice sorgente, la mappa sincronizzata è solo un'implementazione con un mutex (blocco) mentre la ConcurrentHashMap è più complessa per gestire l'accesso simultaneo
Vinze

123
Si noti inoltre che ConcurrentHashMap non consente chiavi o valori null. Quindi NON sono alternative uguali di una mappa sincronizzata.
onejigtwojig,


5
@AbdullahShaikh Il problema sollevato in quell'articolo è stato risolto in Java 7 e ulteriori miglioramenti sono stati apportati in Java 8.
pulse0ne

5
@hengxin: non appena si esegue un'operazione consistente in più query o aggiornamenti della mappa o quando si esegue l'iterazione sulla mappa, è necessario sincronizzare manualmente sulla mappa per garantire coerenza. Le mappe sincronizzate garantiscono la coerenza solo per singole operazioni (invocazioni di metodi) sulla mappa, il che la rende più che spesso inutile in quanto la maggior parte delle operazioni della vita reale sono non banali, quindi è necessario sincronizzare manualmente comunque.
Holger

241
╔═══════════════╦═══════════════════╦═══════════════════╦═════════════════════╗
║   Property    ║     HashMap       ║    Hashtable      ║  ConcurrentHashMap  ║
╠═══════════════╬═══════════════════╬═══════════════════╩═════════════════════╣ 
║      Null     ║     allowed       ║              not allowed                ║
║  values/keys  ║                   ║                                         ║
╠═══════════════╬═══════════════════╬═════════════════════════════════════════╣
║ Thread-safety ║                   ║                                         ║
║   features    ║       no          ║                  yes                    ║
╠═══════════════╬═══════════════════╬═══════════════════╦═════════════════════╣
║     Lock      ║       not         ║ locks the whole   ║ locks the portion   ║        
║  mechanism    ║    applicable     ║       map         ║                     ║ 
╠═══════════════╬═══════════════════╩═══════════════════╬═════════════════════╣
║   Iterator    ║               fail-fast               ║ weakly consistent   ║ 
╚═══════════════╩═══════════════════════════════════════╩═════════════════════╝

Per quanto riguarda il meccanismo di blocco: Hashtable blocca l'oggetto , mentre ConcurrentHashMapblocca solo il secchio .


13
Hashtablenon sta bloccando la parte della mappa. Guarda l'implementazione. Sta usando la synchronizedchiave senza blocco fornito, quindi in pratica significa che si blocca tutto hashtablein ogni operazione.
RMachnik,

6
Che dire di SynapizedMap?
Samuel Edwin Ward,

3
Collections.syncronizedIl comportamento della mappa è come la mappa di supporto, tranne per il fatto che tutti i metodi sono thread-safe
Sergii Shevchyk,

5
Vorrei stampare il tavolo e venderlo per $ 5 ciascuno;). Buono @shevchyk
realPK

Modificato: nessuno dei due è completamente thread-safe. Questo è un po 'fuorviante per i nuovi sviluppatori. Vedere: ibm.com/developerworks/java/library/j-jtp07233/index.html per capire che anche ConcurrentHashMap non è completamente thread-safe da gare di dati esterne. (ad esempio: 1 thread rimuove un valore e un altro tenta in seguito di verificare se è presente e di metterlo in caso contrario. Questa è una condizione di data race e significa comunque che nonostante l'utilizzo di "ConcurrentHashMap" non si è alleviati da tutti i problemi di sicurezza del thread.
Zombi,

142

I "problemi di scalabilità" Hashtablesono presenti esattamente allo stesso modo in Collections.synchronizedMap(Map): usano una sincronizzazione molto semplice, il che significa che solo un thread può accedere alla mappa contemporaneamente.

Questo non è un grosso problema quando hai inserti e ricerche semplici (a meno che tu non lo faccia in modo estremamente intenso), ma diventa un grosso problema quando devi iterare su tutta la Mappa, che può richiedere molto tempo per una grande Mappa - mentre un thread lo fa, tutti gli altri devono aspettare se vogliono inserire o cercare qualcosa.

Gli ConcurrentHashMapusi tecniche molto sofisticate per ridurre la necessità di sincronizzazione e consentire l'accesso in lettura parallela da più thread senza sincronizzazione e, soprattutto, fornisce una Iteratorche non richiede la sincronizzazione e permette anche la mappa da modificare durante interation (anche se non garantisce anche non verranno restituiti elementi inseriti durante l'iterazione).


4
Questo è quello che volevo! :) L'Iteratore non sincronizzato è solo pura dolcezza da solo! Grazie per le informazioni! :) (:
Kounavi il

Ottima risposta ... ma significa che durante il thread di recupero non otterranno gli ultimi aggiornamenti poiché i thread del lettore non sono sincronizzati.
MrA,

@MrA: stai chiedendo la ConcurrentHashMap? E cosa intendi per "recupero"?
Michael Borgwardt,

4
@Michael Borgwardt per ConcurrentHashmap per es. supponiamo che ci siano più thread. alcuni stanno aggiornando la mappa e alcuni stanno ottenendo dati da quella stessa mappa. Pertanto, in questo scenario, quando i thread stanno tentando di leggere, è garantito che otterranno i dati più recenti che sono stati aggiornati poiché i thread del lettore non devono contenere blocchi.
MrA,

35

È preferibile ConcurrentHashMap quando è possibile utilizzarlo, sebbene richieda almeno Java 5.

È progettato per adattarsi bene se utilizzato da più thread. Le prestazioni possono essere leggermente più scarse quando solo un singolo thread accede alla mappa alla volta, ma significativamente migliore quando più thread accedono contemporaneamente alla mappa.

Ho trovato un post sul blog che riproduce una tabella dell'eccellente libro Java Concurrency In Practice , che consiglio vivamente.

Collections.synchronizedMap ha davvero senso solo se devi avvolgere una mappa con alcune altre caratteristiche, forse una sorta di mappa ordinata, come una TreeMap.


2
Sì, sembra che cito quel libro in ogni altra risposta che faccio!
Bill Michell,

Il link @BillMichell è interrotto

@Govinda Disattiva javascript prima di accedere al link. La voce del blog è ancora lì!
Bill Michell,

32

La differenza principale tra questi due è che ConcurrentHashMapbloccherà solo una parte dei dati che vengono aggiornati mentre altre parti sono accessibili da altri thread. Tuttavia, Collections.synchronizedMap()bloccherà tutti i dati durante l'aggiornamento, altri thread possono accedere ai dati solo quando viene rilasciato il blocco. Se ci sono molte operazioni di aggiornamento e relativamente piccole quantità di operazioni di lettura, dovresti scegliere ConcurrentHashMap.

Un'altra differenza è che ConcurrentHashMapnon manterrà l'ordine degli elementi nella mappa passati. È simile a HashMapquando si memorizzano i dati. Non vi è alcuna garanzia che l'ordine degli elementi sia preservato. Mentre Collections.synchronizedMap()conserverà l'ordine degli elementi della Mappa trasmessa. Ad esempio, se passi un TreeMapa ConcurrentHashMap, l'ordine degli elementi in ConcurrentHashMappotrebbe non essere uguale all'ordine in TreeMap, ma Collections.synchronizedMap()preserverà l'ordine.

Inoltre, ConcurrentHashMappuò garantire che non venga ConcurrentModificationExceptiongenerato alcun thread mentre un thread sta aggiornando la mappa e un altro thread sta attraversando l'iteratore ottenuto dalla mappa. Tuttavia, Collections.synchronizedMap()non è garantito su questo.

C'è un post che dimostra le differenze tra questi due e anche il ConcurrentSkipListMap.


13

Mappa sincronizzata:

Anche la mappa sincronizzata non è molto diversa da quella di Hashtable e offre prestazioni simili nei programmi Java simultanei. L'unica differenza tra Hashtable e SynchronizedMap è che SynchronizedMap non è un'eredità e puoi avvolgere qualsiasi mappa per creare la sua versione sincronizzata usando il metodo Collections.synchronizedMap ().

ConcurrentHashMap:

La classe ConcurrentHashMap fornisce una versione concorrente della HashMap standard. Questo è un miglioramento delle funzionalità di SynchronizedMap fornite nella classe Collections.

A differenza della mappa hashtable e sincronizzata, non blocca mai l'intera mappa, invece divide la mappa in segmenti e il blocco viene eseguito su quelli. Funziona meglio se il numero di thread del lettore è maggiore del numero di thread del writer.

ConcurrentHashMap per impostazione predefinita è suddivisa in 16 aree e vengono applicati i blocchi. Questo numero predefinito può essere impostato durante l'inizializzazione di un'istanza ConcurrentHashMap. Quando si impostano i dati in un particolare segmento, si ottiene il blocco per quel segmento. Ciò significa che due aggiornamenti possono comunque essere eseguiti contemporaneamente in modo sicuro se incidono su benne separate, riducendo al minimo la contesa tra i blocchi e massimizzando così le prestazioni.

ConcurrentHashMap non genera un'eccezione ConcurrentModificationException

ConcurrentHashMap non genera ConcurrentModificationException se un thread tenta di modificarlo mentre un altro sta iterando su di esso

Differenza tra synchornizedMap e ConcurrentHashMap

Collections.synchornizedMap (HashMap) restituirà una raccolta che è quasi equivalente a Hashtable, in cui ogni operazione di modifica su Mappa è bloccata sull'oggetto Mappa mentre nel caso di ConcurrentHashMap, la sicurezza del thread si ottiene dividendo l'intera Mappa in una diversa partizione in base al livello di concorrenza e blocca solo una parte particolare invece di bloccare l'intera mappa.

ConcurrentHashMap non consente chiavi null o valori null mentre HashMap sincronizzato consente una chiave null.

Collegamenti simili

link1

Link2

Confronto delle prestazioni


12

Come al solito, ci sono compromessi di concorrenza - spese generali - velocità coinvolti. Devi prendere in considerazione i requisiti di concorrenza dettagliati della tua applicazione per prendere una decisione, quindi testare il codice per vedere se è abbastanza buono.


12

In ConcurrentHashMap, il blocco viene applicato a un segmento anziché a un'intera mappa. Ogni segmento gestisce la propria tabella hash interna. Il blocco viene applicato solo per le operazioni di aggiornamento. Collections.synchronizedMap(Map)sincronizza l'intera mappa.



9

Hai ragione HashTable, puoi dimenticartene.

Il tuo articolo menziona il fatto che, sebbene HashTable e la classe wrapper sincronizzata offrano una sicurezza di thread di base consentendo a un solo thread alla volta di accedere alla mappa, questa non è una "vera" sicurezza di thread poiché molte operazioni composte richiedono ancora una sincronizzazione aggiuntiva, per esempio:

synchronized (records) {
  Record rec = records.get(id);
  if (rec == null) {
      rec = new Record(id);
      records.put(id, rec);
  }
  return rec;
}

Tuttavia, non pensare che ConcurrentHashMapsia una semplice alternativa a HashMapcon un synchronizedblocco tipico come mostrato sopra. Leggi questo articolo per capire meglio le sue complessità.


7

Eccone alcuni:

1) ConcurrentHashMap blocca solo parte della mappa ma SynchronizedMap blocca l'intero MAp.
2) ConcurrentHashMap ha prestazioni migliori rispetto a SynchronizedMap e più scalabile.
3) In caso di lettore multiplo e scrittore singolo ConcurrentHashMap è la scelta migliore.

Questo testo proviene dalla differenza tra ConcurrentHashMap e hashtable in Java


7

Possiamo ottenere la sicurezza dei thread utilizzando ConcurrentHashMap e synchronizedHashmap e Hashtable. Ma c'è molta differenza se guardi alla loro architettura.

  1. synchronisedHashmap e Hashtable

Entrambi manterranno il blocco a livello di oggetto. Quindi, se si desidera eseguire qualsiasi operazione come put / get, è necessario prima acquisire il blocco. Allo stesso tempo, ad altri thread non è consentito eseguire alcuna operazione. Quindi alla volta, solo un thread può operare su questo. Quindi il tempo di attesa aumenterà qui. Possiamo dire che le prestazioni sono relativamente basse quando si confronta con ConcurrentHashMap.

  1. ConcurrentHashMap

Manterrà il blocco a livello di segmento. Ha 16 segmenti e mantiene il livello di concorrenza come 16 per impostazione predefinita. Quindi, alla volta, 16 thread possono essere in grado di operare su ConcurrentHashMap. Inoltre, l'operazione di lettura non richiede un blocco. Quindi qualsiasi numero di thread può eseguire un'operazione get su di esso.

Se thread1 vuole eseguire un'operazione put nel segmento 2 e thread2 vuole eseguire un'operazione put sul segmento 4, è consentito qui. Significa che 16 thread possono eseguire operazioni di aggiornamento (put / delete) su ConcurrentHashMap alla volta.

In modo che il tempo di attesa sarà meno qui. Quindi le prestazioni sono relativamente migliori rispetto a sincronizedHashmap e Hashtable.


1
, 1. cosa succede se più thread tenta di modificare lo stesso blocco? 2. Cosa succede se si dice che due thread tentano di leggere i dati dallo stesso blocco in cui un altro thread sta scrivendo i dati contemporaneamente?
prnjn

6

ConcurrentHashMap

  • È necessario utilizzare ConcurrentHashMap quando è necessaria una concorrenza molto elevata nel progetto.
  • È thread-safe senza sincronizzare l'intera mappa.
  • Le letture possono avvenire molto velocemente mentre la scrittura viene eseguita con un lucchetto.
  • Non è presente alcun blocco a livello di oggetto.
  • Il blocco ha una granularità molto più fine a livello di bucket hashmap.
  • ConcurrentHashMap non genera ConcurrentModificationException se un thread tenta di modificarlo mentre un altro sta iterando su di esso.
  • ConcurrentHashMap utilizza una moltitudine di blocchi.

SynchronizedHashMap

  • Sincronizzazione a livello di oggetto.
  • Ogni operazione di lettura / scrittura deve acquisire il blocco.
  • Il blocco dell'intera raccolta è un sovraccarico di prestazioni.
  • Questo in sostanza dà accesso a un solo thread all'intera mappa e blocca tutti gli altri thread.
  • Potrebbe causare contese.
  • SynchronizedHashMap restituisce Iterator, che fallisce rapidamente in caso di modifiche simultanee.

fonte


4

ConcurrentHashMap è ottimizzato per l'accesso simultaneo.

Gli accessi non bloccano l'intera mappa ma usano una strategia più fine, che migliora la scalabilità. Esistono anche miglioramenti funzionali specifici per l'accesso simultaneo, ad esempio iteratori simultanei.


4

C'è una caratteristica fondamentale da notare ConcurrentHashMapoltre alla funzione di concorrenza che fornisce, che è iteratore a prova di errore . Ho visto gli sviluppatori usare ConcurrentHashMapsolo perché vogliono modificare il entryset - put / remove mentre iterando su di esso. Collections.synchronizedMap(Map)non fornisce iteratore fail-safe ma fornisce invece iteratore fail-fast . gli iteratori fail-fast utilizzano un'istantanea della dimensione della mappa che non può essere modificata durante l'iterazione.


3
  1. Se la coerenza dei dati è estremamente importante, utilizzare Hashtable o Collections.synchronizedMap (Mappa).
  2. Se la velocità / le prestazioni sono estremamente importanti e l'aggiornamento dei dati può essere compromesso, utilizzare ConcurrentHashMap.

2

In generale, se si desidera utilizzare ConcurrentHashMapassicurarsi di essere pronti a perdere gli "aggiornamenti"
(ovvero la stampa dei contenuti di HashMap non garantisce che stamperà la mappa aggiornata) e utilizzare API come CyclicBarrierper garantire la coerenza tra i programmi ciclo vitale.


1

Il metodo Collections.synchronizedMap () sincronizza tutti i metodi di HashMap e lo riduce efficacemente a una struttura di dati in cui un thread può entrare alla volta perché blocca ogni metodo su un blocco comune.

In ConcurrentHashMap la sincronizzazione viene eseguita in modo leggermente diverso. Invece di bloccare tutti i metodi su un blocco comune, ConcurrentHashMap utilizza un blocco separato per bucket separati, bloccando così solo una parte della mappa. Di default ci sono 16 secchi e anche blocchi separati per secchi separati. Quindi il livello di concorrenza predefinito è 16. Ciò significa teoricamente in qualsiasi momento 16 thread possono accedere a ConcurrentHashMap se tutti stanno per separare i bucket.


1

ConcurrentHashMap è stato presentato come alternativa a Hashtable in Java 1.5 come parte del pacchetto di concorrenza. Con ConcurrentHashMap, hai una scelta migliore non solo se può essere tranquillamente utilizzato in un ambiente multi-thread simultaneo, ma offre anche prestazioni migliori rispetto a Hashtable e synchronizedMap. ConcurrentHashMap ha prestazioni migliori perché blocca una parte di Map. Consente operazioni di lettura consentite e allo stesso tempo mantiene l'integrità sincronizzando le operazioni di scrittura.

Come viene implementato ConcurrentHashMap

ConcurrentHashMap è stato sviluppato come alternativa a Hashtable e supporta tutte le funzionalità di Hashtable con capacità aggiuntiva, il cosiddetto livello di concorrenza. ConcurrentHashMap consente a più lettori di leggere contemporaneamente senza utilizzare i blocchi. Diventa possibile separando Mappa in parti diverse e bloccando solo una parte della Mappa negli aggiornamenti. Per impostazione predefinita, il livello di concorrenza è 16, quindi Map è suddiviso in 16 parti e ciascuna parte è gestita da un blocco separato. Significa che 16 thread possono funzionare contemporaneamente con Map, se funzionano con parti diverse di Map. Ciò rende ConcurrentHashMap estremamente produttivo e non compromette la sicurezza dei thread.

Se sei interessato ad alcune importanti funzionalità di ConcurrentHashMap e quando dovresti usare questa realizzazione di Map - Ho appena messo un link a un buon articolo - Come usare ConcurrentHashMap in Java


0

Oltre a ciò che è stato suggerito, vorrei pubblicare il codice sorgente correlato SynchronizedMap .

Per rendere Mapsicuro un thread, possiamo usareCollections.synchronizedMap istruzione e inserire l'istanza della mappa come parametro.

L'implementazione di synchronizedMapin Collectionsè come di seguito

   public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) {
        return new SynchronizedMap<>(m);
    }

Come puoi vedere, l' Mapoggetto di input è avvolto SynchronizedMapdall'oggetto.
Analizziamo l'implementazione di SynchronizedMap,

 private static class SynchronizedMap<K,V>
        implements Map<K,V>, Serializable {
        private static final long serialVersionUID = 1978198479659022715L;

        private final Map<K,V> m;     // Backing Map
        final Object      mutex;        // Object on which to synchronize

        SynchronizedMap(Map<K,V> m) {
            this.m = Objects.requireNonNull(m);
            mutex = this;
        }

        SynchronizedMap(Map<K,V> m, Object mutex) {
            this.m = m;
            this.mutex = mutex;
        }

        public int size() {
            synchronized (mutex) {return m.size();}
        }
        public boolean isEmpty() {
            synchronized (mutex) {return m.isEmpty();}
        }
        public boolean containsKey(Object key) {
            synchronized (mutex) {return m.containsKey(key);}
        }
        public boolean containsValue(Object value) {
            synchronized (mutex) {return m.containsValue(value);}
        }
        public V get(Object key) {
            synchronized (mutex) {return m.get(key);}
        }

        public V put(K key, V value) {
            synchronized (mutex) {return m.put(key, value);}
        }
        public V remove(Object key) {
            synchronized (mutex) {return m.remove(key);}
        }
        public void putAll(Map<? extends K, ? extends V> map) {
            synchronized (mutex) {m.putAll(map);}
        }
        public void clear() {
            synchronized (mutex) {m.clear();}
        }

        private transient Set<K> keySet;
        private transient Set<Map.Entry<K,V>> entrySet;
        private transient Collection<V> values;

        public Set<K> keySet() {
            synchronized (mutex) {
                if (keySet==null)
                    keySet = new SynchronizedSet<>(m.keySet(), mutex);
                return keySet;
            }
        }

        public Set<Map.Entry<K,V>> entrySet() {
            synchronized (mutex) {
                if (entrySet==null)
                    entrySet = new SynchronizedSet<>(m.entrySet(), mutex);
                return entrySet;
            }
        }

        public Collection<V> values() {
            synchronized (mutex) {
                if (values==null)
                    values = new SynchronizedCollection<>(m.values(), mutex);
                return values;
            }
        }

        public boolean equals(Object o) {
            if (this == o)
                return true;
            synchronized (mutex) {return m.equals(o);}
        }
        public int hashCode() {
            synchronized (mutex) {return m.hashCode();}
        }
        public String toString() {
            synchronized (mutex) {return m.toString();}
        }

        // Override default methods in Map
        @Override
        public V getOrDefault(Object k, V defaultValue) {
            synchronized (mutex) {return m.getOrDefault(k, defaultValue);}
        }
        @Override
        public void forEach(BiConsumer<? super K, ? super V> action) {
            synchronized (mutex) {m.forEach(action);}
        }
        @Override
        public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
            synchronized (mutex) {m.replaceAll(function);}
        }
        @Override
        public V putIfAbsent(K key, V value) {
            synchronized (mutex) {return m.putIfAbsent(key, value);}
        }
        @Override
        public boolean remove(Object key, Object value) {
            synchronized (mutex) {return m.remove(key, value);}
        }
        @Override
        public boolean replace(K key, V oldValue, V newValue) {
            synchronized (mutex) {return m.replace(key, oldValue, newValue);}
        }
        @Override
        public V replace(K key, V value) {
            synchronized (mutex) {return m.replace(key, value);}
        }
        @Override
        public V computeIfAbsent(K key,
                Function<? super K, ? extends V> mappingFunction) {
            synchronized (mutex) {return m.computeIfAbsent(key, mappingFunction);}
        }
        @Override
        public V computeIfPresent(K key,
                BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
            synchronized (mutex) {return m.computeIfPresent(key, remappingFunction);}
        }
        @Override
        public V compute(K key,
                BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
            synchronized (mutex) {return m.compute(key, remappingFunction);}
        }
        @Override
        public V merge(K key, V value,
                BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
            synchronized (mutex) {return m.merge(key, value, remappingFunction);}
        }

        private void writeObject(ObjectOutputStream s) throws IOException {
            synchronized (mutex) {s.defaultWriteObject();}
        }
    }

Ciò SynchronizedMapche può essere riassunto come l'aggiunta di un singolo blocco al metodo primario Mapdell'oggetto di input . Tutti i metodi protetti dal blocco non sono accessibili da più thread contemporaneamente. Ciò significa che operazioni normali come pute getpossono essere eseguite da un singolo thread contemporaneamente per tutti i dati Mapnell'oggetto.

Rende Mapora sicuro il thread dell'oggetto, ma le prestazioni potrebbero diventare un problema in alcuni scenari.

Il ConcurrentMapè molto più complicato per l'attuazione, siamo in grado di fare riferimento a Costruire un HashMap meglio per i dettagli. In poche parole, è implementato tenendo conto sia della sicurezza del filo che delle prestazioni.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.