635 votes

Quelle est la différence entre ConcurrentHashMap et Collections.synchronizedMap(Map) ?

J'ai une carte qui doit être modifiée par plusieurs threads simultanément.

Il semble qu'il existe trois implémentations différentes de Map synchronisé dans l'API Java :

  • Hashtable
  • Collections.synchronizedMap(Map)
  • ConcurrentHashMap

D'après ce que j'ai compris, Hashtable est une ancienne implémentation (extension de l'obsolète Dictionary ), qui a été adaptée par la suite pour correspondre à la classe Map l'interface. Bien qu'elle es synchronisée, elle semble avoir de sérieuses les problèmes d'évolutivité et est déconseillé pour les nouveaux projets.

Mais qu'en est-il des deux autres ? Quelles sont les différences entre les cartes renvoyées par Collections.synchronizedMap(Map) y ConcurrentHashMap s ? Laquelle correspond à quelle situation ?

7 votes

@SmilesinaJar Le lien est actuellement rompu, voici une copie archivée de cet article : Pourquoi ConcurrentHashMap est meilleur que Hashtable et aussi bon que HashMap ?

2 votes

IBM : Comment ConcurrentHashMap offre une plus grande concurrence sans compromettre la sécurité des threads @ ibm.com/developerworks/java/library/j-jtp08223/

1 votes

Pour information, Java 6 a apporté ConcurrentSkipListMap en tant qu'autre Map la mise en œuvre. Conçue pour être hautement concurrentielle sous charge, l'utilisation de Sauter la liste algorithme.

440voto

Yuval Adam Points 59423

Pour vos besoins, utilisez ConcurrentHashMap . Il permet la modification simultanée de la carte à partir de plusieurs threads sans qu'il soit nécessaire de les bloquer. Collections.synchronizedMap(map) crée une carte bloquante qui dégrade les performances, mais assure la cohérence (si elle est utilisée correctement).

Utilisez la deuxième option si vous devez assurer la cohérence des données et si chaque thread doit disposer d'une vue actualisée de la carte. Utilisez la première option si les performances sont essentielles et si chaque thread n'insère que des données dans la carte, les lectures étant moins fréquentes.

8 votes

En regardant le code source, la carte synchronisée n'est qu'une implémentation avec un mutex (bloquant) alors que la ConcurrentHashMap est plus complexe pour gérer les accès concurrents.

126 votes

Veuillez également noter que le ConcurrentHashMap n'autorise pas les clés ou les valeurs nulles. Il ne s'agit donc PAS d'alternatives équivalentes à une carte synchronisée.

24 votes

252voto

shevchik Points 6781
╔═══════════════╦═══════════════════╦═══════════════════╦═════════════════════╗
║   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   ║ 
╚═══════════════╩═══════════════════════════════════════╩═════════════════════╝

En ce qui concerne le mécanisme de verrouillage : Hashtable verrouille l'objet , tandis que ConcurrentHashMap serrures seulement le seau .

13 votes

Hashtable n'est pas une partie de la carte qui est verrouillée. Regardez la mise en œuvre. Elle utilise synchronized clé sans serrure, ce qui signifie qu'il verrouille l'ensemble de la clé. hashtable dans chaque opération.

6 votes

Qu'en est-il de la carte synchronisée ?

3 votes

Collections.syncronizedMap a le même comportement que le backing map, sauf que toutes les méthodes sont à l'épreuve des threads.

145voto

Michael Borgwardt Points 181658

Les "problèmes d'évolutivité" pour les Hashtable sont présents exactement de la même manière dans Collections.synchronizedMap(Map) - ils utilisent une synchronisation très simple, ce qui signifie qu'un seul thread peut accéder à la carte en même temps.

Ce n'est pas vraiment un problème lorsque vous effectuez de simples insertions et consultations (à moins que vous ne le fassiez de manière extrêmement intensive), mais cela devient un gros problème lorsque vous devez itérer sur l'ensemble de la carte, ce qui peut prendre beaucoup de temps pour une grande carte - pendant qu'un thread effectue cette opération, tous les autres doivent attendre s'ils veulent insérer ou consulter quelque chose.

En ConcurrentHashMap utilise des techniques très sophistiquées pour réduire le besoin de synchronisation et permettre l'accès à la lecture en parallèle par plusieurs threads sans synchronisation. Iterator qui ne nécessite aucune synchronisation et permet même de modifier la carte pendant l'itération (bien qu'elle ne garantisse pas que les éléments insérés pendant l'itération seront renvoyés).

4 votes

Voilà ce que je voulais ! :) L'itérateur non synchronisé est une pure merveille ! Merci pour l'info ! :) ( :

0 votes

Excellente réponse, mais cela signifie-t-il que, lors de la récupération, le fil de discussion ne recevra pas les dernières mises à jour puisque les fils de discussion des lecteurs ne sont pas synchronisés ?

0 votes

@MrA : Vous posez des questions sur ConcurrentHashMap ? Et qu'entendez-vous par "récupération" ?

35voto

Bill Michell Points 4879

ConcurrentHashMap est préférable lorsque vous pouvez l'utiliser - bien qu'il nécessite au moins Java 5.

Il est conçu pour s'adapter à l'utilisation de plusieurs threads. Les performances peuvent être légèrement inférieures lorsqu'un seul thread accède à la carte à la fois, mais elles sont nettement meilleures lorsque plusieurs threads accèdent à la carte simultanément.

J'ai trouvé un article de blog qui reproduit un tableau tiré de l'excellent livre Concurrence Java en pratique que je recommande vivement.

Collections.synchronizedMap n'a de sens que si vous avez besoin d'envelopper une carte avec d'autres caractéristiques, peut-être une sorte de carte ordonnée, comme une TreeMap.

2 votes

Oui, il semble que je mentionne ce livre dans chacune de mes réponses !

0 votes

Le lien avec @BillMichell est cassé

0 votes

@Govinda Désactivez le javascript avant d'accéder au lien. L'article de blog est toujours là !

14voto

Satish Points 141

En ConcurrentHashMap le verrouillage est appliqué à un segment au lieu d'une carte entière. Chaque segment gère sa propre table de hachage interne. Le verrou n'est appliqué que pour les opérations de mise à jour. Collections.synchronizedMap(Map) synchronise l'ensemble de la carte.

0 votes

Pourriez-vous jeter un coup d'œil ? stackoverflow.com/questions/48579060/ ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X