5

我有一个问题。在我的应用程序中,我有一个 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 的 load-on-startup 为 1,因此它将在启动应用程序时进行初始化。

所以我的问题是为什么我们要同步 init 方法。毕竟它将由 servlet 容器处理,并且只被调用一次。我可以删除上述同步过程还是删除后会对应用程序产生一些影响。

4

3 回答 3

4

init()将仅在 Servlet 在其将创建的单个实例上最初加载到容器中时执行一次。然后doGet()doPost()方法将作为单独的执行线程为每个请求执行。我看不到同步init()方法的任何点或其中的任何代码。即使在分布式环境中,每个 JVM也可能有一个 Servlet 实例。我认为容器足够明智,init()在 Servlet 的生命周期中只调用一次,因此多个线程之间不会有任何争用执行init()。根据Javadocs

servlet 容器在实例化 servlet 后恰好调用一次 init 方法。init 方法必须成功完成,servlet 才能接收任何请求。

于 2013-05-08T09:19:58.803 回答
1

正如评论所说

// This is a safeguard against running init() more than once.

这只是试图保存某种不应该发生的竞争条件。

只要 webapp 存在,任何 Servlet、Filter 和 Listener 都会存在。它们在所有会话中的所有请求之间共享。

所以你可以说 init() 方法在容器中被调用一次。所以不需要有同步块。

但是,您是在 Class-level而不是 object level获得锁,有什么相同的原因吗?您应该检查任何同步的静态调用,这可能是有这个块的正当理由。如果没有,您可以删除相同的。

你可以在这里看到一些很好的解释

于 2013-05-08T09:21:02.947 回答
0

总的来说,我同意你的评价。

它似乎没有实现单线程,因此删除“同步”不应该受到伤害。

另一方面,它几乎不会导致性能损失,因此去除只是为了“减少杂质”。

于 2013-05-08T09:23:20.363 回答