我有一个问题。在我的应用程序中,我有一个servlet,其初始化代码如下所示。
public class GameInitServlet extends HttpServlet {
private static boolean initialized = false;
@Override
public void init() throws ServletException {
// This is a safeguard against running init() more than once.
synchronized (GameInitServlet.class) {
if (initialized) {
LOG.error("GameInitServlet has already been initialized... Bailing out!");
return;
}
initialized = true;
}
//some code here....
}
}
注意:在web.xml中 上面的servlet在启动时加载为1,因此它会在启动应用程序时初始化。
所以我的问题是为什么我们要同步init方法。毕竟它将由servlet容器处理并且只被调用一次。 我是否可以删除上述同步过程,或者在删除此应用程序后会对应用程序产生一些影响。
答案 0 :(得分:3)
init()
将仅执行一次。然后将为每个请求执行doGet()
和doPost()
方法作为单独的执行线程。我没有看到任何同步init()
方法或其中的任何代码的点。即使在分布式环境中,每个JVM也可能有一个Servlet实例 。我认为Container足够明智,只能在Servlet的生命周期内调用init()
一次,因此不会有任何争用。多个线程来执行init()
。根据{{3}},
servlet容器在实例化servlet后只调用一次init方法。在servlet可以接收任何请求之前,init方法必须成功完成。
答案 1 :(得分:1)
正如评论所说
// This is a safeguard against running init() more than once.
这只是试图挽救一些永远不会发生的种族条件。
只要webapp存在,任何Servlet,过滤器和监听器都会存在。它们在所有会话中的所有请求中共享。
所以你可以说init()方法在容器中被调用一次。因此不需要同步块。
但是,你是在级别而不是在对象级别进行锁定,原因是什么?您应该检查任何同步的静态调用,可能有一个有效的原因有此块。如果没有,你可以删除它。
您可以看到一些很好的解释here
答案 2 :(得分:0)
总的来说,我同意你的评估。
它似乎没有实现单线程,因此删除“sychronized”不应该受到伤害。
另一方面,它几乎不会导致性能损失,因此移除仅仅是为了“减少”。