静态初始化的 unmodifyingCollection.get 保证不可变吗?
静态初始化的 unmodifyingCollection.get 保证不可变吗?
对于:
静态最终映射 FOO = Collections.unmodifyingMap(new HashMap());
多个线程使用 get 方法是否可以避免出现问题?
即使 FOO 中的项目无法添加/删除,是什么阻止 get 方法出于缓存目的而操纵 FOO 的内部状态等。如果以任何方式修改内部状态,则不能同时使用 FOO。如果是这样的话,java中真正的不可变集合在哪里呢?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
给出具体的例子:
那么 FOO 将是不可变的。它也永远不会有任何元素。考虑到更一般的情况:
那么这是否是不可变的完全取决于其他人是否可以访问底层 Map,以及它是什么类型的 Map。例如,如果它是 LinkedHashMap,则底层链表可以通过访问顺序进行修改,并且可以通过调用 get() 进行更改。最安全的方法(使用非并发类)是:
HashMap 的 javadocs 意味着只要您不对映射进行结构更改,那么同时使用它就是安全的,因此这对于您可以使用的任何访问器来说都是安全的使用,即获取各种集合并迭代它们,然后 get() 应该是安全的。
如果您可以使用并发类,那么您也可以这样做:
这对于多线程使用来说是显式安全的,因为 ConcurrentHashMap 是显式多线程访问安全的。内部状态可能是可变的,但外部可见状态不会,并且由于该类保证是线程安全的,因此我们可以安全地认为它是外部不可变的。
Given the specific example:
Then FOO will be immutable. It will also never have any elements. Given the more general case of:
Then whether or not this is immutable is entirely dependent on whether or not someone else can get to the underlying Map, and what type of Map it is. For example, if it is a LinkedHashMap then the underlying linked list could be modified by access order, and could change by calling get(). The safest way (using non-concurrent classes) to do this would be:
The javadocs for HashMap imply that so long as you make no structural changes to the map, then it is safe to use it concurrently, so this should be safe for any of the accessors that you can use, that is getting the various sets and iterating over them and get() should then be safe.
If you can use the concurrent classes, then you could also do:
This will be explicitly safe to use from multiple threads, since ConcurrentHashMap is explicitly multi-thread access safe. The internal state might be mutable, but the externally visible state will not be, and since the class is guaranteed to be threadsafe, we can safely consider it to be externally immutable.
冒着听起来像是我在疯狂做广告的风险,请使用 Google 不可变集合 并完成它。
At the risk of sounding like I'm on an advertising spree, use the Google Immutable Collections and be done with it.
其实是个好问题。想想
WeakHashMap
- 它可以在不调用突变操作的情况下进行更改。访问顺序模式下的LinkedHashMap
大致相同。HashMap
状态的 API 文档:大概这应该是当且仅当。这意味着如果
HashMap
是“有效不可变”,则get
不需要同步。Actually a good question. Think
WeakHashMap
- that can change without having a mutation operation called on it.LinkedHashMap
in access-order mode is much the same.The API docs for
HashMap
state:Presumably that should be if and only if. That means that
get
does not need to be synchronised if theHashMap
is 'effectively immutable'.Java SDK 中不存在真正的不可变映射。克里斯建议的所有地图都只是线程安全的。不可修改的 Map 也不是不可变的,因为如果底层 Map 发生更改,也会出现 ConcurrentModificationException 。
如果您想要真正不可变的映射,请使用 Google Collections / Guava 中的 ImmutableMap。
There is no true immutable map in Java SDK. All of the suggested Maps by Chris are only thread safe. The unmodifiable Map is not immutable either since if the underlying Map changed there will
ConcurrentModificationException
as well.If you want the truly immutable map, use ImmutableMap from Google Collections / Guava.
我建议任何线程操作使用 ConcurrentHashMap 或 HashTable,两者都是线程安全的。
I would suggest for any threaded operation to use ConcurrentHashMap or HashTable, both are thread-safe.
返回的映射上的 getter 是否碰巧与某些内部状态发生冲突并不重要,只要对象遵守其契约(即成为无法修改的映射)。所以你的问题是“找错树”。
如果您没有对其所包装的地图的所有权和控制权,那么您对 UnmodifyingMap 保持谨慎是正确的。例如
Whether a getter on the returned map happens to twiddle with some internal state is unimportant, as long as the object honors its contract (which is to be a map that cannot be modified). So your question is "barking up the wrong tree".
You are right to be cautious of UnmodifiableMap, in the case where you do not have ownership and control over the map it wraps. For example