WeakHashMap迭代和垃圾收集 [英] WeakHashMap iteration and garbage collection

查看:145
本文介绍了WeakHashMap迭代和垃圾收集的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用 WeaekHashMap 来实现缓存。我想知道我是否正在迭代这个地图的键,同时垃圾收集器正在主动从这个地图中删除键,我会收到 ConcurrentModificationException 吗?
我不这么认为,因为据我所知,concurrentmodificationexception因为应用程序代码中的错误而发生,开发人员忘记了解相同的映射是由其他线程共享/使用的,在这种情况下,应该没有发生。但是想知道当WeakHashMap未同步时JVM如何处理这个?

I am using a WeaekHashMap to implement a Cache. I am wondering if I am iterating over the keys of this map, and at the same time garbage collector is actively removing keys from this map, would I receive a ConcurrentModificationException ? I do not think so, because as far as I understand, concurrentmodificationexception happens because of bugs in the application code where the developer forgot to understand that the same map is shared/used by other threads and in this case, it should not happen. But wondering how would JVM handle this when WeakHashMap is not synchronized ?

推荐答案

正如bkail所说,当GC删除一个条目时一个 WeakHashMap 它不会导致并发修改。实际上,GC通过对 WeakReference 对象(包含真实密钥)本身的硬引用来收集底层对象。因此,不会收集由地图直接引用的真实对象(引用对象),因此在您的某个线程调用此映射中的方法之前,映射不会更改。此时,映射会检查GC中的引用队列,并查找已收集的所有键并将其从映射中删除 - 因此对映射结构的实际更改将发生在您的某个线程上。

As bkail said, when GC "removes" an entry from a WeakHashMap it is not going to cause a concurrent modification. In reality the GC collects the underlying object by there is a hard reference to WeakReference object (that holds the real key) itself. Therefore, the real object (the reference object) that is directly referenced by the map is not collected so the map does not change until one of your threads calls a method in this map. At that time the map checks the reference queue from the GC and finds all keys that have been collected and removes them from the map - so the actual changes to the map structure occurs on one of your threads.

在考虑这个问题时,可能会出现一种情况,你可能会在这样的地图中得到一个你不会在另一种地图中得到的并发修改 - 如果你放了一个已存在的密钥或者调用一个getter方法。但实际上,在并发应用程序中你应该锁定这些调用,所以你的程序中会有一个真正的并发访问错误。

In thinking of this then there may be one case where you may get a concurrent modification in such a map that you would not get in another kind of map - if you put a key that already exists or call a getter method. But really, in a concurrent application you should be locking around these calls anyway so you would have a really concurrent access bug in your program.

这是回答你的问题问题,你真的不应该使用 WeakHashMap 来获取缓存(即使你在谈论缓存密钥)。在缓存中,当不再引用值时,您不希望您的值神奇地消失。通常,当有一定的最大数量时,你希望它们消失(类似于Apache集合 LRUMap )或根据内存需求发布。

That being said in answer to your question, you really should not use WeakHashMap for a cache (even if you were talking about caching keys). In a cache you don't want your values 'magically' disappearing when the values are no longer referenced. Typically you want them to disappear when there is a certain maximum number (something like Apache collections LRUMap) or released on memory demand.

对于后者,您可以使用带有 SoftReference 的地图(Apache集合提供 ReferenceMap 允许您指定键或值的引用类型。指定软引用仅基于内存压力释放 - 另一方面弱引用必须通过GC识别出对象没有剩余硬引用并且可以随时释放它。当然,软参考如何真正起作用也取决于JVM的实现。

For the later, you can use a map with a SoftReference (Apache collections provides a ReferenceMap that allows you to specify the kind of reference for either the key or value). A soft reference is specified to only be released based on memory pressure - a weak reference on the other hand has to do more with GC recognizing that there are no hard reference remaining to the object and can release it at any time. Of course, how a soft reference really works is also dependent on the JVM implementation.

编辑:我重读了你的问题,想要解决一个其他一点。因为实际修改发生在您自己的线程上的 WeakHashMap 内部结构中,如果您只在单个线程中使用此映射,则不需要同步任何方法调用。此行为与任何其他 Map 没有什么不同。

EDIT: I reread your question and want to address one other point. Because the actual modifications occur to the WeakHashMap internal structures on your own thread, if you only use this map in a single thread you do not need to synchronize any method calls. This behavior is no different than any other Map.

这篇关于WeakHashMap迭代和垃圾收集的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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