java.util.HashMap中的无限循环

我在这里经常有一些Vaadin代码阻塞,我不知道问题是什么:

Thread 7892: (state = IN_JAVA) - java.util.HashMap.getEntry(java.lang.Object) @bci=61, line=349 (Compiled frame; information may be imprecise) - java.util.HashMap.containsKey(java.lang.Object) @bci=2, line=335 (Compiled frame) - java.util.HashSet.contains(java.lang.Object) @bci=5, line=184 (Compiled frame) - com.vaadin.ui.Table.unregisterPropertiesAndComponents(java.util.HashSet, java.util.HashSet) @bci=85, line=1693 (Compiled frame) - com.vaadin.ui.Table.refreshRenderedCells() @bci=992, line=1641 (Compiled frame) - com.vaadin.ui.Table.valueChange(com.vaadin.data.Property$ValueChangeEvent) @bci=23, line=2897 (Compiled frame) - com.vaadin.data.util.IndexedContainer.firePropertyValueChange(com.vaadin.data.util.IndexedContainer$IndexedContainerProperty) @bci=140, line=553 (Compiled frame) - com.vaadin.data.util.IndexedContainer.access$1000(com.vaadin.data.util.IndexedContainer, com.vaadin.data.util.IndexedContainer$IndexedContainerProperty) @bci=2, line=64 (Compiled frame) - com.vaadin.data.util.IndexedContainer$IndexedContainerProperty.setValue(java.lang.Object) @bci=202, line=915 (Compiled frame) - com.aimprosoft.wavilon.backgroundthreads.ChangeCdrThread.insertNewPersonIntoTable(com.aimprosoft.wavilon.model.Person, com.vaadin.ui.HorizontalLayout, com.aimprosoft.wavilon.ui.menuitems.CallContent, com.vaadin.ui.Table) @bci=924, line=208 (Interpreted frame) - com.aimprosoft.wavilon.backgroundthreads.ChangeCdrThread$RepaintTableThread.run() @bci=622, line=446 (Compiled frame) 

有人可以建议任何方法来进一步调试这个问题吗? 问题很少发生,重现起来非常困难。

根据它在代码中的位置,我能想到的唯一解释是有多个线程访问和更新HashMap而没有正确同步。 这可能导致映射的数据结构被破坏,并可能导致无限循环。

我想不出java.util.HashMap.getEntry会阻塞的任何其他原因。 它不执行任何同步或任何I / O.


Roland Illig评论:

行号确实表明代码在其中一个e = e.next循环中挂起。

这支持了我的假设。 由两个(或更多)线程执行的对散列表的特定操作序列导致在一个散列链中创建循环/循环。 发生此损坏是因为执行操作的线程之间的同步不足。 这种情况很少发生,但一旦发生,腐败就不会消失。

如果不深入研究Vaadin源代码,我无法确切地告诉您它是否是Vaadin错误,或者是您使用 Vaadin的方式中的错误。 这两种解释都是合情合理的。

UPDATE

基于这篇文章 (在下面的评论中提供),我会说它很可能是你的应用程序同步(或不同步)的方式的问题。

所以你在这里看到的是一个进入无限循环的线程,评估e = e.next

在本质上

e.next == e

当您在表重组期间通过多个线程放入HashMap时会发生这种情况。

请查看此链接以获取更多信息

一个美丽的比赛条件

要解决此问题,请使用Collections.synchronizedMapConcurrentHashMap 。 我建议后者。

修改组件时,后台线程是否在应用程序实例上同步? 如果没有,那那就是你的问题。