Java Concurrency: Volatile vs finale dans les variables « en cascade »?
-
23-10-2019 - |
Question
est
final Map<Integer,Map<String,Integer>> status = new ConcurrentHashMap<Integer, Map<String,Integer>>();
Map<Integer,Map<String,Integer>> statusInner = new ConcurrentHashMap<Integer, Map<String,Integer>>();
status.put(key,statusInner);
la même chose que
volatile Map<Integer,Map<String,Integer>> status = new ConcurrentHashMap<Integer, Map<String,Integer>>();
Map<Integer,Map<String,Integer>> statusInner = new ConcurrentHashMap<Integer, Map<String,Integer>>();
status.put(key,statusInner);
dans le cas où la carte intérieure est accessible par différents threads?
ou est encore quelque chose comme cela nécessaire:
volatile Map<Integer,Map<String,Integer>> status = new ConcurrentHashMap<Integer, Map<String,Integer>>();
volatile Map<Integer,Map<String,Integer>> statusInner = new ConcurrentHashMap<Integer, Map<String,Integer>>();
status.put(key,statusInner);
Dans le cas où l'on est pas un « cascade » carte, ont en fin de finale et volatile le même effet que de faire shure toutes les discussions voient toujours le contenu correct de la carte ... Mais qu'advient-il si la carte contient iteself une carte, comme dans l'exemple ... Comment puis-je faire shure que la carte intérieure est correctement « mémoire délimitée par des barrières »?
Tanks! Tom
La solution
volatile
affecte uniquement la capacité des autres threads de lire la valeur des variables qu'il est attaché. Il ne modifie en rien la capacité d'un autre thread pour voir les clés et les valeurs de la carte. Par exemple, je pourrais avoir un volatile int[]
. Si je change la référence i.e.. si je change le tableau réel qu'il pointe à d'autres threads lecture du tableau sont garantis pour voir ce changement. Cependant, si je change le troisième élément du tableau de telles garanties ne sont faites.
Si status
est final
, la construction de la classe contenant une relation de type happens-before
avec une lecture ultérieure, de sorte qu'ils sont en mesure de voir la valeur de l'état. De même lit tout à votre variable volatile
sont garantis pour voir la dernière affectation de référence. Il est à la différence de vous échanger la carte réelle autour très souvent, plus comme vous êtes juste en train de changer les clés et les séjours d'ensemble d'objets de la carte comme est.
Pour cette question, alors, nous devons consulter la documentation ConcurrentHashMap
:
opérations de recherche (y compris get) généralement ne pas bloquer, peut donc se chevaucher avec des opérations de mise à jour (y compris mettre et supprimer). Récupérations reflètent la les résultats du plus récent les opérations de mise à jour sur leur tenue apparition.
est un peu curieusement formulée, mais l'essentiel est que toute opération de get
dont l'apparition est après un peu le retour de l'opération de put
est garanti pour voir les résultats de cette vente. Donc, vous n'avez même pas besoin d'un volatile
sur la carte extérieure; Quoth JLS:
Un fil qui ne peut voir une référence à un objet après que l'objet a été est complètement initialisés garantie pour voir correctement le valeurs initialisées pour que son objet champs final.
Résumé
A final
sur la carte externe est suffisante.
Autres conseils
Il est intéressant de regarder Google-collections et, en particulier, MapMaker qui vous permet de configurer intelligemment et de créer des cartes. Être en mesure de configurer des valeurs faibles pour permettre une meilleure collecte des ordures et des temps d'expiration, de sorte que vous pouvez utiliser Maps pour la mise en cache efficace, est brillante. Comme les cartes qui fait MapMaker (: p). Ont les mêmes propriétés que ConcurrentHashMap, vous pouvez être heureux avec son fil de sécurité
final mapMaker = new MapMaker().weakValues(); //for convenience, assign
final Map<Integer,Map<String,Integer>> status = mapMaker.makeMap();
status.put(key, mapMaker.<String, Integer>makeMap());
S'il vous plaît note, vous voudrez peut-être regarder votre définition de statusInner, car il ne semble pas juste.
Je pense que la meilleure réponse est que volatile
n'est pas un moyen d'assurer la sécurité-fil.
L'utilisation ConcurrentHashMap
est à peu près tout ce que vous avez besoin. Oui, faire la référence au Map
niveau supérieur final
si vous le pouvez, mais volatile
n'est pas nécessaire en tout état de cause. Le deuxième niveau de référence de Map
sont à l'intérieur de l'entreprise ConcurrentHashMap
pour obtenir le droit, et l'on suppose qu'il fait.