DWR并发异常


52818 java.util.ConcurrentModificationException
52819 at java.util.HashMap$HashIterator.nextEntry(HashMap.java:793)
52820 at java.util.HashMap$ValueIterator.next(HashMap.java:822)
52821 at org.directwebremoting.impl.DefaultScriptSessionManager.checkTimeouts(DefaultScriptSessionManager.java:179)
52822 at org.directwebremoting.impl.DefaultScriptSessionManager.maybeCheckTimeouts(DefaultScriptSessionManager.java:163)
52823 at org.directwebremoting.impl.DefaultScriptSessionManager.getScriptSession(DefaultScriptSessionManager.java:50)
52824 at org.directwebremoting.impl.DefaultWebContext.getScriptSession(DefaultWebContext.java:83)
52825 at org.directwebremoting.dwrp.BaseCallMarshaller.marshallOutbound(BaseCallMarshaller.java:305)
52826 at org.directwebremoting.servlet.PlainCallHandler.handle(PlainCallHandler.java:53)
52827 at org.directwebremoting.servlet.UrlProcessor.handle(UrlProcessor.java:101)
52828 at org.directwebremoting.servlet.DwrServlet.doPost(DwrServlet.java:146)
52829 at com.netease.photo.webapp.web.servlets.PhotoDwrServlet.doPost(PhotoDwrServlet.java:51)
52830 at javax.servlet.http.HttpServlet.service(HttpServlet.java:709)
52831 at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
52832 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
52833 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
52834 at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:265)
52835 at com.netease.photo.security.filter.NEAccessInfoFilter.doFilter(NEAccessInfoFilter.java:55)
52836 at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
52837 at com.netease.photo.security.filter.NEFilterSecurityInterceptor.doFilter(NEFilterSecurityInterceptor.java:49)
52838 at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
52839 at com.netease.photo.security.filter.NEAnonymousProcessingFilter.doFilter(NEAnonymousProcessingFilter.java:234)
52840 at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
52841 at com.netease.photo.security.filter.NEAuthenticationProcessingFilter.doFilter(NEAuthenticationProcessingFilter.java:300)
52842 at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
52843 at com.netease.photo.security.filter.NEExceptionTranslationFilter.doFilter(NEExceptionTranslationFilter.java:62)


问题代码,报出异常原因是sessionMap有变化,导致modCount和expectedModCount不相等,判断了checkForComodification()后,抛出异常
protected void checkTimeouts()
{
long now = System.currentTimeMillis();
List timeouts = new ArrayList();

synchronized (sessionLock)
{
for (Iterator it = sessionMap.values().iterator(); it.hasNext();)
{
DefaultScriptSession session = (DefaultScriptSession) it.next();

if (session.isInvalidated())
{
continue;
}

long age = now - session.getLastAccessedTime();
if (age > scriptSessionTimeout)
{
timeouts.add(session);
}
}

for (Iterator it = timeouts.iterator(); it.hasNext();)
{
DefaultScriptSession session = (DefaultScriptSession) it.next();
session.invalidate();
}
}
}


具有改变sessionMap的源码
public RealScriptSession getScriptSession(String id)
{
maybeCheckTimeouts();

synchronized (sessionLock)
{
DefaultScriptSession scriptSession = (DefaultScriptSession) sessionMap.get(id);
if (scriptSession == null)
{
scriptSession = new DefaultScriptSession(id, this);
* sessionMap.put(id, scriptSession);*
}
else
{
scriptSession.updateLastAccessedTime();
}

return scriptSession;
}
}


protected void invalidate(RealScriptSession scriptSession)
{
// Can we think of a reason why we need to sync both together?
// It feels like a deadlock risk to do so
synchronized (sessionLock)
{
*RealScriptSession removed = (RealScriptSession) sessionMap.remove(scriptSession.getId());*
if (!scriptSession.equals(removed))
{
log.debug("ScriptSession already removed from manager. scriptSession=" + scriptSession + " removed=" + removed);
}

int removeCount = 0;
for (Iterator it = pageSessionMap.values().iterator(); it.hasNext();)
{
Set pageSessions = (Set) it.next();
boolean isRemoved = pageSessions.remove(scriptSession);

if (isRemoved)
{
removeCount++;
}
}

if (removeCount != 1)
{
log.debug("DefaultScriptSessionManager.invalidate(): removeCount=" + removeCount + " when invalidating: " + scriptSession);
}
}
}


http://directwebremoting.org/jira/browse/DWR-536
这个是我们遇到的问题.
The problem is when using an iterator of a synchonized map; when using an iterator, the map (even when it is synchronized) should be synchronized while iterating...
即使对hashmap外部做了synchronized,在iterator的时候hashmap还是不安全的。(这里不安全的原因还在调查,估计跟jvm有关)
有两种解决方案
1.对hashmap在iterator之前做一次拷贝
2.对hashmap做同步,可以使用concurrenthashmap

在dwr后面的几次版本更新中已经有了修改
/* */ protected final ConcurrentMap sessionMap;
/* */ protected final ConcurrentMap> pageSessionMap;

/* 527 */ this.sessionMap = new ConcurrentHashMap();
/* */
/* 535 */ this.pageSessionMap = new ConcurrentHashMap();


http://pengtyao.iteye.com/blog/1074271
conCurrentHashMap再iterator的时候
http://stackoverflow.com/questions/3768554/is-iterating-concurrenthashmap-values-thread-safe
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值