Java 并发:“级联”中的 Volatile 与 Final变量?
?
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);
相同吗
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);
与内部 Map 由不同线程访问的情况
或者甚至需要这样的东西:
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);
如果它不是“级联”映射,则最终和易失性最终具有相同的效果,使所有线程始终看到映射的正确内容......但是会发生什么如果 Map 本身包含一个地图,如示例中所示...我如何确保内部 Map 正确地“内存屏障”?
坦克! 汤姆
is
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);
the same as
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);
in case the inner Map is accessed by different Threads?
or is even something like this required:
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);
In case the it is NOT a "cascaded" map, final and volatile have in the end the same effect of making shure that all threads see always the correct contents of the Map... But what happens if the Map iteself contains a map, as in the example... How do I make shure that the inner Map is correctly "Memory barriered"?
Tanks!
Tom
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
易失性
仅影响其他线程读取其所附加的变量值的能力。它绝不会影响另一个线程查看映射的键和值的能力。例如,我可以有一个volatile int[]
。如果我更改引用(即,如果我更改它指向的实际数组),则读取该数组的其他线程一定会看到该更改。但是,如果我更改数组的第三个元素,则不会做出这样的保证。如果
status
为final
,则包含类的构造会与任何后续读取创建happens-before
关系,因此它们能够看到地位的价值。同样,对易失性
变量的任何读取都保证会看到对其的最新引用分配。这与您经常交换实际地图不同,更像是您只是更改键并且整个地图对象保持原样。那么对于这个问题,我们需要查阅ConcurrentHashMap的文档:
这种措辞有点奇怪,但要点是,任何在某个
put
操作返回之后开始的get
操作都保证能看到结果那把。所以你甚至不需要在外部地图上使用易失性
; JLS 说道:总结
外部地图上的
final
就足够了。volatile
only affects the ability of other threads to read the value of the variables it's attached to. It in no way affects the ability of another thread to see the keys and values of the map. For instance, I could have avolatile int[]
. If I change the reference—i.e. if I change the actual array that it points to—other threads reading the array are guaranteed to see that change. However, if I change the third element of the array no such guarantees are made.If
status
isfinal
, the construction of the containing class creates ahappens-before
relationship with any subsequent reads, so they are able to see the value of status. Likewise any reads to yourvolatile
variable are guaranteed to see the latest reference assignment to it. It's unlike you're swapping the actual map around very often, more like you're just changing keys and the overall map object stays as is.For this question, then, we need to consult the documentation for
ConcurrentHashMap
:This is kind of oddly worded, but the gist is that any
get
operation whose onset is after someput
operation's return is guaranteed to see the results of that put. So you don't even need avolatile
on the outer map; quoth the JLS:Summary
A
final
on the outer map is sufficient.Google 集合值得一看,尤其是MapMaker 可让您智能地设置和创建地图。能够设置弱值,以实现更好的垃圾收集和过期时间,以便您可以使用映射进行有效的缓存,这真是太棒了。由于 MapMaker 制作的 Map (:p) 具有与 ConcurrentHashMap 相同的属性,因此您可以对其线程安全性感到满意。
请注意,您可能需要查看 statusInner 的定义,因为它看起来不正确。
It's worth looking at Google-Collections and, in particular, MapMaker that lets you intelligently setup and create Maps. Being able to setup weak values, to enable better garbage collection, and expiration times, so you can use Maps for effective caching, is brilliant. As the Maps that MapMaker makes (:p) have the same properties as ConcurrentHashMap, you can be happy with its thread-safety.
Please note, you might want to look at your definition of statusInner, as it doesn't seem right.
我认为这里最好的答案是易失性不是确保线程安全的方法。
使用 ConcurrentHashMap 几乎就是您所需要的。是的,如果可以的话,请引用顶级
Map
final
,但在任何情况下都不需要volatile
。内部的第二级 Map 引用是 ConcurrentHashMap 的职责,人们认为它是正确的。I think the best answer here is that
volatile
is not a way to ensure thread-safety.Using
ConcurrentHashMap
is pretty much all you need. Yes, make the reference to the top-levelMap
final
if you can, butvolatile
is not necessary in any event. The second-levelMap
reference inside are the business ofConcurrentHashMap
to get right, and one assumes it does.