我们遇到一个问题,很多用户都在点击一个有很多ajax调用的页面。我们花了很长时间才倒闭,最后在LoadableDetachableModel中发现了一个线程问题。
我认为问题与我们在Session中有UserModel的事实有关。此UserModel扩展了LoadableDetachableModel。如果load()方法返回时间过长,那么第二个Thread可能会获得null用户返回的基于以下事实:在调用load()之前和设置transientModelObject之前,附加标志设置为true。为了解决这个问题,我们只需创建自己的LoadableDetachableModel修改版本,在必要时添加同步。从那以后我们就没有问题了。
我在Wicket Jira网站环顾四周,甚至看了一些鱼眼内部的提交,看看这个问题是否已经修复,因为我注意到Wicket 7没有附加标志。相反,它有一个名为InternalState的枚举来修复WICKET-5916。似乎线程问题仍然存在于7.2版本的wicket中。这是代码:
@Override
public final T getObject()
{
if (state == null || state == InternalState.DETACHED)
{
// prevent infinite attachment loops
state = InternalState.ATTACHING;//<--One thread sets this, next thread gets a null object returned since load() has not completed
transientModelObject = load();
if (log.isDebugEnabled())
{
log.debug("loaded transient object " + transientModelObject + " for " + this +
", requestCycle " + RequestCycle.get());
}
state = InternalState.ATTACHED;
onAttach();
}
return transientModelObject;
}
如您所见,如果单个线程调用getObject()并转到调用load()的行,则模型将状态变量设置为ATTACHING。现在,下一个线程在load()完成之前调用getObject()并获取返回的null对象,因为state不为null且状态不是DETACHED。
同样,我认为只有在Session或Application类中使用LoadableDetachableModel时才会发生这种情况,其中多个线程可以重用相同的模型。
我错过了什么或者我应该提交错误报告吗?我不应该在Session中使用LoadableDetachableModel吗?
答案 0 :(得分:3)
IModel是Components使用的接口,所有组件都是单线程的。 不要在会话或应用程序中使用模型。