8
votes

Une taille de Java Hashmap () peut-elle être hors de synchronisation avec la taille de ses entrées réelles?

J'ai un haschmap Java appelé StatonCountMap.
Taille d'appel () Résultats de 30.
Mais si je compte les entrées manuellement, c'est 31
Ceci est dans l'un de mes tests d'unité de test. Ces résultats ci-dessous proviennent de la fenêtre d'affichage Eclipse (code de type -> Highlight -> Hit Afficher le résultat de l'évaluation du texte sélectionné).

private void incrementCountInMap(Map map, Long id, String qualifier) {
    String key = id + "-" + qualifier;
    if (map.get(key) == null) {
        map.put(key, 0);
    }
    synchronized (map) {
        map.put(key, map.get(key).intValue() + 1);
    }
}


4 commentaires

Pouvez-vous montrer tout le code? Peut-être que l'une est une entrée par défaut, essayez 20 entrées, voir si vous obtenez 21


Je compte juste combien d'entrées il y a dans {40534-inactif = 2, 40526-inactive = 1, 40528-inactif = 1, 40492-inactif = 3, 40492-Total = 4, 40513-Total = 6, 40532-Draft = 4, 40524-Total = 7, 40526-Draft = 2, 40528-actif = 1, 40524-Draft = 2, 40515-actif = 1, 40513-Draft = 4, 40534-Draft = 1, 40514-Total = 3, 40529-Draft = 4, 40515-Total = 3, 40492-actif = 1, 40528-Total = 4, 40514-Draft = 2, 40526-Total = 3, 40524-Inactive = 2, 40515-Draft = 2, 40514- Actif = 1, 40534-Total = 3, 40513-actif = 2, 40528-Draft = 2, 40532-Total = 4, 40524-actif = 3, 40529-actif = 1, 40529-Total = 5}


J'accepte la réponse de chacun (par Peter Lawrey, Stephen C, NSFyn55 et spécial merci également à Thomas Mueller d'écrire ce cas de test). Mais je peux choisir seulement 1. Merci tout le monde.


Je pense avoir le même problème, mais ce n'est pas vraiment un problème. Il ne suffit pas de compter manuellement les entrées car vous devez également compter tous les conflits de hachage pour chaque clé.


4 Réponses :


12
votes

Je pense que vous pouvez y parvenir si vous modifiez une clé après son addition à un hashmap.

Toutefois, dans votre cas, il semble s'agir d'un cas de modification de la même carte dans deux threads sans synchronisation correcte. par exemple. dans le fil a, carte.put (clé, 0), fil b map.put (Key2, 0) peut entraîner une taille de 1 ou 2. Si vous faites la même chose avec supprimer, vous pouvez vous retrouver avec une taille plus grande que vous devrait.


1 commentaires

Vous voulez dire clé = nouvelle anenty (); map.put (clé, 1); carte.Size () est 1 à ce stade; key.setmember ("xyz"); map.Size () n'est plus 1? Pouvez-vous me montrer un exemple? Je ne pense pas que ce soit le cas ici car toutes les modifications sont effectuées par incrémentCountTInmap () et je ne modifie pas les clés.



2
votes

Le problème que la première carte.put (..) n'est pas synchronisée. Synchroniser ou utiliser collections.synchronizedMap (..) code>. Cas d'essai:

size: 11 entries: {k3=24, k4=20, k5=16, k6=30, k7=16, k8=18, k9=11, k0=18, k1=16, k1=13, k2=18}
size: 11 entries: {k3=18, k4=19, k5=21, k6=20, k7=18, k8=26, k9=20, k0=16, k1=25, k2=15}
size: 11 entries: {k3=25, k4=20, k5=27, k6=15, k7=17, k8=17, k9=24, k0=21, k1=16, k1=1, k2=17}
size: 11 entries: {k3=13, k4=21, k5=18, k6=21, k7=13, k8=17, k9=25, k0=20, k1=23, k2=28}
size: 11 entries: {k3=21, k4=25, k5=19, k6=12, k7=17, k8=14, k9=23, k0=24, k1=26, k2=18}
size: 9 entries: {k3=13, k4=17, k5=23, k6=24, k7=18, k8=19, k9=28, k0=21, k1=17, k2=20}
size: 9 entries: {k3=15, k4=24, k5=21, k6=18, k7=21, k8=30, k9=20, k0=17, k1=15, k2=19}
size: 11 entries: {k3=15, k4=13, k5=21, k6=21, k7=15, k8=19, k9=23, k0=30, k1=15, k2=27}
size: 11 entries: {k3=29, k4=15, k5=19, k6=19, k7=15, k8=23, k9=14, k0=31, k1=18, k2=12}
size: 11 entries: {k3=17, k4=18, k5=20, k6=11, k6=13, k7=20, k8=22, k9=30, k0=12, k1=21, k2=16}


0 commentaires

4
votes

hmmm ... Après avoir relire mon message, pourrait-il être à cause de l'exécution simultanée de bloc-bloquage extérieur de synchronisation (clé) == null & carte.put (clé, 0) qui cause ce problème?

Dans un mot ... Oui.

Hashmap n'est pas le fil-coffre-fort. Par conséquent, s'il existe un point où deux threads pourraient mettre à jour un hashmap sans la synchronisation correcte, la carte pourrait entrer dans un état incohérent. Et même si l'un des threads n'est que la lecture, ce fil pourrait voir un état incohérent pour la carte.

La bonne façon d'écrire cette méthode est la suivante: < Pré> xxx


0 commentaires

4
votes

Si vous utilisez la capacité initiale de 16 par défaut de 16 et que vous accédez à une carte dans une manière non fil de sécurité de votre mûre pour un état incohérent. La taille est un membre de l'état de la carte mise à jour car chaque élément est entré (taille ++). En effet, la carte elle-même est une gamme de listes liées et ne peut pas vraiment renvoyer sa taille réelle, car il n'est pas indicatif du nombre d'articles qu'il contient. Une fois que la carte a atteint un pourcentage (load_factor) de la capacité totale, il doit se redéfinir pour accueillir davantage d'éléments. Si un thread de Rogue tente d'ajouter des éléments car la carte est redimensionnée qui sait quel état la carte sera dans.


0 commentaires