WeakHashMap迭代和垃圾回收

问题描述

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

考虑到这一点,那么在某些情况下,您可能会在这样的映射中进行并发修改,而您不会在另一种映射中得到并发修改- 如果您放置已经存在的键或调用getter方法。但是,实际上,在并发应用程序中,无论如何,您都应该锁定这些调用,以便在程序中存在真正的并发访问错误

话虽如此,您实际上 WeakHashMap用于缓存(即使您正在谈论缓存密钥)。在缓存中,当不再引用值时,您不希望您的值“神奇地”消失。通常,您希望它们在有一定的最大数量时(例如Apache collectionsLRUMap)消失,或者根据内存需求释放它们。

对于以后的版本,您可以将地图与一起使用SoftReference(Apache集合提供了一个地图ReferenceMap,可让您指定键或值的引用类型)。指定软引用只能根据内存压力来释放- 另一方面,弱引用必须与GC一起做更多事情,因为它认识到对象没有剩余的硬引用,可以随时释放它。当然,软引用的实际工作方式还取决于JVM的实现。

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

解决方法

我正在使用WeaekHashMap实现缓存。我想知道是否要遍历此映射的键,同时垃圾回收器正在主动从此映射中删除键,我会收到ConcurrentModificationException吗?我不这么认为,因为据我所知,并发修改异常是由于应用程序代码中的错误而发生的,开发人员忘记了同一个映射是由其他线程共享/使用的,因此在这种情况下,应该不会发生。但是想知道当WeakHashMap不同步时JVM将如何处理吗?