javax.servlet.Servlet的线程安全性#getServletConfig()

时间:2016-11-08 11:12:05

标签: java multithreading tomcat servlets thread-safety

我想知道为什么调用javax.servlet.Servlet#getServletConfig()是线程安全的:如果你检查实现 来自servlet API 3.0.1的javax.servlet.GenericServlet,您会看到以下内容:

package javax.servlet;

// lines omitted

public abstract class GenericServlet 
    implements Servlet, ServletConfig, java.io.Serializable
{
    // lines omitted

    private transient ServletConfig config;

    // lines omitted

    public void init(ServletConfig config) throws ServletException {
    this.config = config;
    this.init();
    }

    // lines omitted

    public ServletConfig getServletConfig() {
    return config;
    }
    // lines omitted
}

字段config写在init(ServletConfig)中,没有任何同步,锁定或config是易失性的,而getServletConfig()可以随时从servlet的任何后续工作线程调用容器。我快速浏览了Tomcat / Catalina代码库,但是我没有看到servlet容器执行任何魔术的迹象,这可以保证从configgetServletConfig()的线程安全访问。 javax.servlet.GenericServlet#service(ServletRequest, ServletResponse)以及javax.servlet.http.HttpServlet中的相应方法。

我在这里遗漏了什么吗?什么将保证如果线程A用于init(ServletConfig),则线程B调用getServletConfig()将看到字段config的正确状态(Java "发生在...之前&# 34; ),而不是例如null

1 个答案:

答案 0 :(得分:0)

ServletConfig是一个单例对象(由容器管理),您只能在servlet init-parameters阶段使用它来检索servletcontext或获取init或servletname 。 你不能向ServletConfig对象写任何东西,而只有容器管理这个对象,因此,它是线程安全的。

字段配置是用init(ServletConfig)编写的,没有任何同步,锁定或配置是易失性的,而getServletConfig()可以随时从servlet容器的任何后续工作线程调用吗?

GenericServlet是一个抽象类,容器不会为其创建任何对象,而是容器为您编写/提供的自定义HttpServlet类创建一个对象(默认情况下只有一个实例)通过它初始化ServletConfig对象。

问题是关于getServletConfig()而不是ServletConfig的线程安全性?

一旦容器在servlet生命周期ServletConfig阶段创建init对象,它就永远不会被更改。因此,getServletConfig()是线程安全的(即,只要没有任何线程允许向其写入任何内容,读取ServletConfig对象的线程数无关紧要。)

  

更新的问题:

     

如果线程A用于init(ServletConfig),将保证什么   然后线程B调用getServletConfig()将看到正确的状态   字段配置(Java"发生在之前"),而不是例如空?

servlet容器在实例化servlet后只调用一次init方法。 在servlet可以接收任何请求之前,init方法必须成功完成。 如果init方法抛出ServletException或者在Web服务器定义的时间段内没有返回,则servlet容器不能将servlet置于服务中。您可以查看here

只有在init()方法成功完成后才会创建用户请求线程。因此,用户请求之间不需要数据(servletconfig)同步线程因为 servletconfig对象在创建用户请求线程之前已经可用