我想知道为什么调用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容器执行任何魔术的迹象,这可以保证从config
到getServletConfig()
的线程安全访问。 javax.servlet.GenericServlet#service(ServletRequest, ServletResponse)
以及javax.servlet.http.HttpServlet
中的相应方法。
我在这里遗漏了什么吗?什么将保证如果线程A用于init(ServletConfig)
,则线程B调用getServletConfig()
将看到字段config
的正确状态(Java "发生在...之前&# 34; ),而不是例如null
?
答案 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
对象在创建用户请求线程之前已经可用。