Je lisais la documentation officielle d'Oracle sur la concurrence en Java et je me demandais quelle pouvait être la différence entre un Collection
retourné par
public static <T> Collection<T> synchronizedCollection(Collection<T> c);
et en utilisant par exemple un
ConcurrentHashMap
. Je suppose que j'utilise synchronizedCollection(Collection<T> c)
sur une HashMap
. Je sais qu'en général, une collection synchronisée est essentiellement un décorateur pour ma HashMap
; il est donc évident qu'une ConcurrentHashMap
a quelque chose de différent en interne. Avez-vous des informations sur ces détails de mise en œuvre?
Edit: je me suis rendu compte que le code source est accessible au public:ConcurrentHashMap.Java
Je voudrais lire le source de ConcurrentHashMap car il est assez compliqué dans les détails. En bref, il a
ConcurrentHashMap
est très similaire à la classe Java.util.HashTable
, sauf que ConcurrentHashMap
offre une meilleure simultanéité que HashTable
ou synchronizedMap
. ConcurrentHashMap
ne verrouille pas la carte pendant que vous la lisez. De plus, ConcurrentHashMap
ne verrouille pas l'intégralité de la Map
lorsque vous y écrivez. Il ne verrouille que la partie de la Map
sur laquelle vous écrivez, en interne.
Une autre différence est que ConcurrentHashMap ne jette pas ConcurrentModificationException
si la ConcurrentHashMap
est modifiée lors de son itération. La Iterator
n'est pas conçue pour être utilisée par plus d'un thread, alors que synchronizedMap
peut lancer ConcurrentModificationException
C'est l'article qui m'a aidé à le comprendre Pourquoi ConcurrentHashMap est meilleur que Hashtable et aussi bon qu'un HashMap
Hashtable offre un accès simultané à leurs entrées, avec une petite mise en garde, la carte entière est verrouillée pour effectuer toute sorte d'opération . Alors que cette surcharge est ignorable dans une application Web sous normale sous charge lourde, cela peut entraîner des retards de réponse et surtaxer votre serveur sans raison valable.
C’est là que ConcurrentHashMap intervient. Ils offrent toutes les fonctionnalités de Hashtable avec une performance presque aussi bonne qu'un HashMap . ConcurrentHashMap y parvient par un mécanisme très simple . Au lieu d'un verrou large sur la carte, la collection conserve une liste de 16 verrouille par défaut, chacun étant utilisé pour protéger (ou verrouiller) un seul seau de la carte. Cela signifie que 16 threads peuvent modifier la collection en une seule fois (tant qu’ils travaillent tous sur des compartiments différents ). Enfait il n'y a pas d'opération effectuée par ce collection qui verrouille la carte entière. Le niveau de simultanéité du collection, le nombre de threads pouvant le modifier en même temps sans blocage, peut être augmenté. Cependant, un nombre plus élevé signifie plus frais généraux liés au maintien de cette liste de verrous.
Les "problèmes d’évolutivité" de Hashtable
se présentent 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 avez de simples insertions et des recherches (sauf si vous le faites de manière extrêmement intensive), mais cela devient un gros problème lorsque vous devez parcourir l'ensemble de la carte, ce qui peut prendre beaucoup de temps pour une grande carte - un fil fait cela, tous les autres doivent attendre s'ils veulent insérer ou rechercher quoi que ce soit.
La ConcurrentHashMap
utilise des techniques très sophistiquées pour réduire le besoin de synchronisation et permettre un accès en lecture parallèle à plusieurs threads sans synchronisation. Elle fournit surtout un Iterator ne nécessitant aucune synchronisation et permettant même de modifier la m si les éléments insérés lors de l'itération seront retournés).
Renvoyé par synchronizedCollection () est un objet dont toutes les méthodes sont synchronisées sur this , de sorte que toutes les opérations simultanées sur cet emballage sont sérialisées. ConcurrentHashMap est un conteneur réellement simultané avec un verrouillage à grain fin optimisé pour maintenir le conflit aussi bas que possible. Regardez le code source et vous verrez ce qu’il contient.
ConcurrentHashMap implémente ConcurrentMap qui fournit la simultanéité . Deep en interne, ses itérateurs sont conçus pour être utilisés par un seul thread à la fois qui maintient la synchronisation . Cette carte est largement utilisée en simultanéité.