如果我在HttpServlet #init(ServletConfig)中分配实例字段,Servlet规范是否保证我可以在doGet()中读取它们?

Dav*_*ock 5 java servlets specifications thread-safety

Servlet规范规定容器将实例化我的单个实例java.servlet.HttpServlet,并从多个工作线程调用服务方法(doGet()/ doPost()).

根据正常的线程规则,不能保证init(ServeltConfig)"之前发生的" 实例级字段的分配由执行的其他线程从那些相同的字段读取doGet(),除非有人在某个时刻安排同步.

实际上,容器实际上可以进行某种外部同步,以确保init()"后续"线程可以看到完成的工作.

但是,Servlet规范是否明确保证我是线程安全的?我现在无法找到这样的保证,虽然我必须承认,自从Servlet 2.4以来,我还没有从端到端读取规范.

编辑

例如,由于一些回答者将事情搞砸了,我的问题是:Servlet规范是什么说下面的类是线程安全的?

@WebServlet (initParams = {@WebInitParam(name="b", value="true")})
public Decider extends HttpServlet {

    private boolean b = false;

    public void init(ServletConfig config) {
        this.b = Boolean.parseBoolean(config.getAttribute("b"));
    }

    public void doGet(HttpServletRequest req, HttpServletResponse res) {
        res.sendRedirect(b ? "/true" ? "/false");
    }

}
Run Code Online (Sandbox Code Playgroud)

当然,如果我这样做:

public static void main(String[] argv) {

      HttpServlet s = new Decider();

      Thread t1 = new Thread(new Runnable() {
        public void run() {
            s.init(...);
        }
      });

      Thread t2 = new Thread(new Runnable() {
        public void run() {
            s.doGet(...);
        }
      });

      t1.start();
      t2.start();
}
Run Code Online (Sandbox Code Playgroud)

...然后我有一个线程错误.什么使容器必然不同?

编辑2

所有声称"容器处理它"的答案当然是受欢迎的,但我的问题是关于Servlet规范是否保证这种行为.要充分回答这个问题,你必须参考Servlet规范.(任何版本,我都很酷).

kan*_*kan 7

这在init javadoc中明确说明:

在实例化servlet之后,servlet容器只调用一次init方法.在servlet可以接收任何请求之前,init方法必须成功完成.

如果你遵循servlet生命周期,它会说initservice多个线程的请求之前应该有一个servlet .

  • @DavidBullock我认为有一个答案:http://stackoverflow.com/questions/11719916/marking-servlet-instance-variables-defined-in-init-as-volatile.所以你可以假设`GenericServlet`是如何实现的. (2认同)