Question

Je suis à la recherche à un code existant qui a l'idiome suivant:

Map<String, Boolean> myMap = someGlobalInstance.getMap();
synchronized (myMap) {
    item = myMap.get(myKey);
}

L'avertissement que je reçois des inspections de code de Intelli-J est:

Synchronization on local variable 'myMap'

Est-ce la synchronisation appropriée et pourquoi?

Map<String, Boolean> myMap = someGlobalInstance.getMap();
synchronized (someGlobalInstance.getMap()) {
    item = myMap.get(myKey);
}
Était-ce utile?

La solution

La raison pour cela est signalé comme un problème parce que la synchronisation des variables locales est généralement une mauvaise idée.

Si l'objet retourné par someGlobalInstance.getMap() est toujours le même, le bloc synchronisé n'utilise en fait que les objets quasi-globale surveiller et le code produit le résultat attendu.

Je suis également d'accord avec la suggestion d'utiliser un wrapper synchronisé, si vous avez seulement besoin de synchroniser les appels get() / put() et ne pas plus gros blocs synchronisés. Mais assurez-vous que la carte est uniquement accessible via l'emballage ou vous aurez une autre chance pour les bugs.

Notez également que si someGlobalInstance.getMap() ne pas retourner le même objet tout le temps, alors même votre deuxième exemple de code ne fonctionnera pas correctement, il pourrait même être pire que votre code d'origine puisque vous pouvez synchroniser sur un objet différent de celui que vous appelez get() sur.

Autres conseils

Je pense que le code pourrait être son, en fonction de la méthode getMap () fait. Si elle garde une référence à une instance qui doit être partagé entre les threads il est logique. L'avertissement est sans importance puisque la variable locale n'est pas initialisé localement.

Je pense qu'il serait préférable d'utiliser wrapper synchronisé pour votre carte

Alex est correct que l'ajout d'une enveloppe synchronisée en appelant Collections.synchronizedMap(Map) est une approche typique ici. Cependant, si vous prenez cette approche, il peut encore y avoir des situations où vous devez synchroniser sur le verrouillage du Map; par exemple. lorsque vous parcourez la carte.

Map<String, String> syncMap = Collections.synchronizedMap(new HashMap<String, String>());

// Synchronized on map to prevent ConcurrentModificationException whilst iterating.
synchronized (syncMap) {
  for (Map.Entry<String, String> entry : syncMap.entrySet()) {
    // Do work
  }
}

Dans votre exemple, l'avertissement d'IDEA peut être ignorée, car il est évident que votre variable locale: map est récupéré d'ailleurs (someGlobalInstance) plutôt que d'être créée au sein de la méthode, et peut donc être potentiellement accessible à partir d'autres threads.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top