Je suis tombé sur le morceau de code suivant et j'ai noté quelques incohérences - pour un code multi-thread sécurisé.
Map<String,Map<String,Set<String>> clusters = new HashMap<.........>; Map<String,Set<String>> servers = clusters.get(clusterkey); if(servers==null){ synchronized(clusterkey){ servers = clusters.get(clusterkey); if(servers==null){....initialize new hashmap and put...} } } Set<String> users=servers.get(serverkey); if(users==null){ synchronized(serverkey){ users=servers.get(serverkey); if(users==null){ ... initialize new hashset and put...} } } users.add(userid);
3 Réponses :
1 -La synchronisation essaie d'éviter que deux threads, en même temps, créent une nouvelle entrée dans cette carte. Le second doit attendre pour que son (servers == null)
ne renvoie pas également true
.
2 - Cette liste des utilisateurs
semble être hors de portée, mais il semble qu'elle ne nécessite pas de synchronisation. Peut-être que le programmeur sait qu'il n'y a pas d'ID utilisateur dupliqué, ou peut-être qu'il ne se soucie pas de réinitialiser le même utilisateur encore et encore.
3- ConcurrentHashMap peut-être?
Voici juste quelques observations:
chaîne
est une très mauvaise idée < / a> -> la synchronisation sur clusterKey
et serverKey
ne fonctionnera probablement pas comme prévu. ConcurrentHashMap
et les ConcurrentHashSet
. Bien que sans plus de contexte, il n'est pas vraiment possible de répondre à cette question. Il semble que l'auteur du code ait voulu créer en toute sécurité un seul mappage par clusterKey
et serverKey
afin que l'utilisateur puisse être ajouté une seule fois.
Une manière (probablement meilleure) serait de simplement synchroniser
sur la carte clusters
elle-même et alors vous êtes en sécurité car un seul thread peut lire et / ou écrire dit la carte.
Une autre façon serait d'utiliser des Lock
personnalisés, peut-être un pour la lecture et un autre pour l'écriture, bien que cela puisse à nouveau conduire à des incohérences si un thread écrit sur la Map < / code> pendant qu'un autre lit cette valeur exacte.
Le code ressemble à une version non réfléchie de Idiome de verrouillage vérifié à deux reprises < / a> qui est parfois utilisé pour une initialisation paresseuse. Lisez le lien fourni pour savoir pourquoi cette implémentation est vraiment mauvaise.
Le problème avec le code donné est qu'il échoue par intermittence. Il y a une condition de concurrence quand il y a plusieurs threads essayant de travailler sur la carte en utilisant la même clé (ou des clés avec le même hashcode) ce qui signifie que la carte créée en premier peut être remplacée par la seconde hashmap.
Cela ne peut pas vraiment être considéré comme une réponse de lien, mais cela pourrait quand même être un commentaire. Peut-être ajouter une citation et / ou un code de la page wikipedia que vous avez fournie, peut-être suggérer une solution?
L'OP voulait des commentaires sur ce que fait le code, pas une solution pour le faire fonctionner de manière cohérente. Mais je peux fournir plus de détails.
Il n'y a pas de bien et de mal tant que nous ne connaissons pas le contexte exact. L'extrait de code que vous avez fourni n'est pas suffisant pour nous dire ce que pense l'implémenteur d'origine.