当前位置: 首页 > 面试题库 >

WeakHashMap迭代和垃圾回收

卢健
2023-03-14
问题内容

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


问题答案:

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

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

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

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

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



 类似资料:
  • 问题内容: 首先,我想澄清一下我的理解,因为以下问题是相同的。 上面代码的输出是 这意味着,尽管一旦GC运行,实际的对象对象就会被垃圾回收,但是内存中仍然有一个类对象,该对象此时不指向任何对象。 现在考虑到上述理解为真,我对工作原理感到困惑。在下面的代码中 输出: 现在的 问题 是,据说输入是弱引用,这意味着在上面的代码中, 成为实际对象时可以进行垃圾回收,因为不再有对该对象的强引用,但是 和作为

  • 垃圾回收 我们对生产中花了很多时间来调整垃圾回收。垃圾回收的关注点与Java大致相似,尽管一些惯用的Scala代码比起惯用的Java代码会容易产生更多(短暂的)垃圾——函数式风格的副产品。Hotspot的分代垃圾收集通常使这不成问题,因为短暂的(short-lived)垃圾在大多情形下会被有效的释放掉。 在谈GC调优话题前,先看看这个Attila的报告,它阐述了我们在GC方面的一些经验。 Scal

  • 对于开发者来说,JavaScript 的内存管理是自动的、无形的。我们创建的原始值、对象、函数……这一切都会占用内存。 当我们不再需要某个东西时会发生什么?JavaScript 引擎如何发现它并清理它? 可达性(Reachability) JavaScript 中主要的内存管理概念是 可达性。 简而言之,“可达”值是那些以某种方式可访问或可用的值。它们一定是存储在内存中的。 这里列出固有的可达值的

  • 垃圾收集,引用计数,显式分配 和所有的现代语言一样,OCaml提供垃圾收集器,所以你不用像C/C++一样显式地分配和释放内存。 JWZ在他的文章 "Java sucks" rant(Java蛋疼(怒)!): 第一个好家伙是Java没有 free()。其他的都没有所谓了。这几乎掩盖了所有的缺点,不管有多糟糕, 这个有点让后续文档基本都没有意义了,但是...(译注:但是啥大家自己看吧) OCaml的垃

  • 问题内容: 这是我到目前为止所读的内容,如果我写错了,请更正我: Node.js基于V8 JavaScript引擎。 V8 JavaScript引擎实现了世界垃圾收集 这导致Node.js有时完全关闭几秒钟到几分钟来处理垃圾回收。 如果这是为生产代码运行的,那么对于10,000个用户而言,这是几秒钟。 这在生产环境中真的可以接受吗? 问题答案: 是否可接受取决于您的应用程序和堆大小。Big Gc约

  • Go 开发者不需要写代码来释放程序中不再使用的变量和结构占用的内存,在 Go 运行时中有一个独立的进程,即垃圾收集器(GC),会处理这些事情,它搜索不再使用的变量然后释放它们的内存。可以通过 runtime 包访问 GC 进程。 通过调用 runtime.GC() 函数可以显式的触发 GC,但这只在某些罕见的场景下才有用,比如当内存资源不足时调用 runtime.GC(),它会在此函数执行的点上立