Quelle est la différence entre l'utilisation de la classe wrapper,, SynchronizedMap
sur un HashMap
et ConcurrentHashMap
?
Est-il simplement capable de modifier le HashMap
tout en l'itérant ( ConcurrentHashMap
)?
Quelle est la différence entre l'utilisation de la classe wrapper,, SynchronizedMap
sur un HashMap
et ConcurrentHashMap
?
Est-il simplement capable de modifier le HashMap
tout en l'itérant ( ConcurrentHashMap
)?
Réponses:
Synchronisé HashMap
:
Chaque méthode est synchronisée à l'aide d'un verrou au niveau de l'objet. Ainsi, les méthodes get et put de synchMap acquièrent un verrou.
Le verrouillage de la collection entière est une surcharge de performance. Pendant qu'un thread s'accroche au verrou, aucun autre thread ne peut utiliser la collection.
ConcurrentHashMap
a été introduit dans JDK 5.
Il n'y a pas de verrouillage au niveau de l'objet, le verrouillage est à une granularité beaucoup plus fine. Pour a ConcurrentHashMap
, les verrous peuvent être au niveau du seau de hashmap.
L'effet du verrouillage de niveau inférieur est que vous pouvez avoir des lecteurs et des enregistreurs simultanés, ce qui n'est pas possible pour les collections synchronisées. Cela conduit à beaucoup plus d'évolutivité.
ConcurrentHashMap
ne lance pas un ConcurrentModificationException
si un thread essaie de le modifier pendant qu'un autre l'itère.
Cet article Java 7: HashMap vs ConcurrentHashMap est une très bonne lecture. Hautement recommandé.
ConcurrentHashMap
le size()
résultat pourrait être obsolète. size()
est autorisé à renvoyer une approximation au lieu d'un décompte exact selon le livre "Java Concurrency in Practice". Cette méthode doit donc être utilisée avec précaution.
La réponse courte:
Les deux cartes sont des implémentations thread-safe de l' Map
interface. ConcurrentHashMap
est implémenté pour un débit plus élevé dans les cas où une forte concurrence est attendue.
L' article de Brian Goetz sur l'idée derrière ConcurrentHashMap
est une très bonne lecture. Hautement recommandé.
Map m = Collections.synchronizedMap(new HashMap(...));
docs.oracle.com/javase/7/docs/api/java/util/HashMap.html
ConcurrentHashMap
est thread-safe sans synchroniser toute la carte. Les lectures peuvent se produire très rapidement tandis que l'écriture se fait avec un verrou.
Nous pouvons assurer la sécurité des threads en utilisant à la fois ConcurrentHashMap et synchronisedHashmap. Mais il y a beaucoup de différence si vous regardez leur architecture.
Il maintiendra le verrou au niveau de l'objet. Donc, si vous voulez effectuer une opération comme put / get, vous devez d'abord acquérir le verrou. Dans le même temps, les autres threads ne sont autorisés à effectuer aucune opération. Donc à la fois, un seul thread peut opérer sur cela. Le temps d'attente augmentera donc ici. Nous pouvons dire que les performances sont relativement faibles lorsque vous comparez avec ConcurrentHashMap.
Il maintiendra le verrou au niveau du segment. Il comporte 16 segments et maintient le niveau de concurrence à 16 par défaut. Ainsi, à la fois, 16 threads peuvent fonctionner sur ConcurrentHashMap. De plus, l'opération de lecture ne nécessite pas de verrou. Ainsi, n'importe quel nombre de threads peut effectuer une opération get dessus.
Si thread1 veut effectuer une opération de mise dans le segment 2 et que thread2 veut effectuer une opération de mise sur le segment 4, alors cela est autorisé ici. Cela signifie que 16 threads peuvent effectuer une opération de mise à jour (insertion / suppression) sur ConcurrentHashMap à la fois.
Pour que le temps d'attente soit moindre ici. Par conséquent, les performances sont relativement meilleures que synchronisedHashmap.
Les deux sont une version synchronisée de HashMap, avec des différences dans leurs fonctionnalités de base et leur structure interne.
ConcurrentHashMap se compose de segments internes qui peuvent être considérés comme des HashMaps indépendants sur le plan conceptuel. Tous ces segments peuvent être verrouillés par des threads séparés dans des exécutions simultanées élevées. Ainsi, plusieurs threads peuvent obtenir / placer des paires clé-valeur à partir de ConcurrentHashMap sans se bloquer / attendre les uns les autres. Ceci est mis en œuvre pour un débit plus élevé.
tandis que
Collections.synchronizedMap () , nous obtenons une version synchronisée de HashMap et on y accède de manière bloquante. Cela signifie que si plusieurs threads tentent d'accéder à synchronizedMap en même temps, ils seront autorisés à obtenir / placer des paires clé-valeur une par une de manière synchronisée.
ConcurrentHashMap
utilise un mécanisme de verrouillage plus fin connu sous le nom lock stripping
de permettre un plus grand degré d'accès partagé. Pour cette raison, il offre une meilleure concurrence et une meilleure évolutivité .
De plus, les itérateurs renvoyés pour ConcurrentHashMap
sont faiblement cohérents au lieu de la technique d' échec rapide utilisée par Synchronized HashMap.
Les méthodes en SynchronizedMap
attente maintiennent le verrou sur l'objet, alors ConcurrentHashMap
qu'il existe un concept de "bande de verrouillage" où les verrous sont maintenus sur des seaux de contenu à la place. Amélioration de l'évolutivité et des performances.
ConcurrentHashMap:
1) Les deux maps sont des implémentations thread-safe de l'interface Map.
2) ConcurrentHashMap est implémenté pour un débit plus élevé dans les cas où une forte concurrence est attendue.
3) Il n'y a pas de verrouillage au niveau de l'objet.
Carte de hachage synchronisée:
1) Chaque méthode est synchronisée à l'aide d'un verrou de niveau objet.
ConcurrentHashMap permet un accès simultané aux données. La carte entière est divisée en segments.
Lire l'opération ie. get(Object key)
n'est pas synchronisé même au niveau du segment.
Mais écrire des opérations ie. remove(Object key), get(Object key)
acquérir le verrouillage au niveau du segment. Seule une partie de la carte entière est verrouillée, les autres threads peuvent toujours lire les valeurs de divers segments sauf celui verrouillé.
SynchronizedMap , d'autre part, acquiert le verrouillage au niveau de l'objet. Tous les threads doivent attendre le thread actuel quelle que soit l'opération (lecture / écriture).
Un test de performances simple pour ConcurrentHashMap vs Synchronized HashMap
. Le flux de test appelle put
un thread et get
trois threads Map
simultanément. Comme @trshiv l'a dit, ConcurrentHashMap a un débit et une vitesse plus élevés pour les opérations de lecture sans verrouillage. Le résultat est que lorsque la durée des opérations est terminée 10^7
, ConcurrentHashMap est 2x
plus rapide que Synchronized HashMap.
SynchronizedMap
et ConcurrentHashMap
sont tous deux de classe thread-safe et peuvent être utilisés dans une application multithread, la principale différence entre eux concerne la manière dont ils assurent la sécurité des threads.
SynchronizedMap
acquiert le verrouillage sur toute l'instance de la carte, tandis que celle-ci ConcurrentHashMap
divise l'instance de la carte en plusieurs segments et le verrouillage est effectué sur ceux-ci.
Selon java doc
Hashtable et Collections.synchronizedMap (nouveau HashMap ()) sont synchronisés. Mais ConcurrentHashMap est "simultané".
Une collection simultanée est thread-safe, mais n'est pas régie par un seul verrou d'exclusion.
Dans le cas particulier de ConcurrentHashMap, il autorise en toute sécurité n'importe quel nombre de lectures simultanées ainsi qu'un nombre réglable d'écritures simultanées. Les classes «synchronisées» peuvent être utiles lorsque vous devez empêcher tout accès à une collection via un seul verrou, au détriment d'une moindre évolutivité.
Dans d'autres cas où plusieurs threads sont censés accéder à une collection commune, les versions "simultanées" sont normalement préférables. Et les collections non synchronisées sont préférables lorsque les collections ne sont pas partagées ou ne sont accessibles que lorsque d'autres verrous sont maintenus.
Hashtable
etSynchronized HashMap
?