Java并发:“级联”中的易失性vs最终变量? [英] Java Concurrency : Volatile vs final in "cascaded" variables?

查看:119
本文介绍了Java并发:“级联”中的易失性vs最终变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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);

或者甚至是这样所需的:

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);

如果它不是一个级联映射,final和volatile效果,使所有线程总是看到Map的正确内容...但是如果Map iteself包含一个映射,如在示例中,会发生什么...如何使内部Map正确的内存阻塞?

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"?

坦克!
Tom

Tanks! Tom

推荐答案

volatile 线程读取它附加的变量的值。它不会影响另一个线程查看地图的键和值的能力。例如,我可以有一个 volatile int [] 。如果我改变引用 - 即。如果我改变它指向的实际数组,读取数组的其他线程保证看到这种变化。然而,如果我改变数组的第三个元素没有这样的保证。

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 a volatile 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.

如果 status final ,包含类的构造会创建一个 happens-before 与任何后续读取的关系,因此他们能够看到状态值。同样,对 volatile 变量的任何读操作都将保证看到它的最新引用分配。这不像你经常交换实际的地图,更像是你只是改变键,整个地图对象保持原样。

If status is final, the construction of the containing class creates a happens-before relationship with any subsequent reads, so they are able to see the value of status. Likewise any reads to your volatile 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.

对于这个问题, ,我们需要查阅 ConcurrentHashMap 的文档:

For this question, then, we need to consult the documentation for ConcurrentHashMap:


检索操作)
一般不阻塞,因此可能与更新操作重叠
(包括put
和remove)。检索结果反映了最近完成的
更新操作的
结果,保持了他们的
开始。

Retrieval operations (including get) generally do not block, so may overlap with update operations (including put and remove). Retrievals reflect the results of the most recently completed update operations holding upon their onset.

这是一种奇怪的措辞,但要点是任何 get 操作,其开始之后 put 操作的返回是保证看到的结果。所以你甚至不需要在外部映射上的 volatile quots the JLS:

This is kind of oddly worded, but the gist is that any get operation whose onset is after some put operation's return is guaranteed to see the results of that put. So you don't even need a volatile on the outer map; quoth the JLS:


一个线程只能在对象
之后才能看到引用
完全初始化是
,保证正确的
初始化的对象
final字段的值。

A thread that can only see a reference to an object after that object has been completely initialized is guaranteed to see the correctly initialized values for that object's final fields.



总结



外部映射上的 final 就足够了。

这篇关于Java并发:“级联”中的易失性vs最终变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆