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



我想知道为什么调用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
}

字段configinit(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 "happens-before"),而不是例如null ?

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

字段配置在init(ServletConfig)中写入,没有任何同步,锁定或配置不稳定,而getServletConfig()可以随时从servlet容器的任何后续工作线程调用?

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

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

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

更新问题:

如果线程A被用来init(ServletConfig)然后线程B调用getServletConfig()将看到正确的状态字段配置(Java"happens-before"),而不是例如null?

servlet容器在实例化servlet之后只调用一次init方法。 init方法必须成功完成,servlet才能接收任何请求。如果init方法抛出ServletException或在Web服务器定义的时间段内没有返回,servlet容器就不能将servlet放入服务中。你可以看这里

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

最新更新