参考:Head First Servlets & JSP, page 204, 第三题:
问:“实现 SingleThreadModel 的效果实际上与同步服务方法的效果相同。两者都可以在不保护会话和上下文状态的情况下使 Web 应用程序瘫痪。”
这是什么意思:“在不保护会话和上下文状态的情况下让 Web 应用程序崩溃”?他们是说实现 SingleThreadModel 不够线程安全吗?因为即使一次只能在一个 servlet 上运行一个线程,这并不能阻止其他 servlet 访问和改变上下文/会话范围的变量?`
这是对的。
如果 Servlet 实现了 SingleThreadingModel,那么为什么需要保护会话状态?它一次只允许一个线程。我认为,即使您打开一个新的浏览器窗口,servlet 也不允许您发出两个请求。
这是不正确的。你可以有另一个选项卡、另一个窗口或其他任何东西。您可能无法同时访问同一个 Servlet,因为您可能会被阻止,但您可以访问另一个也访问相同 Context 或 Session 的 Servlet。而且,根据 API,允许同一个 Servlet 的多个实例在不同的线程中提供多个响应(唯一的限制是一个实例不能为多个线程提供服务)。
也许它们意味着不同的 Servlet 一次只有一个线程,如果它们不同步该状态,它们仍然可能破坏上下文/会话状态?
为什么类(静态)变量不是线程安全的?因为所有线程都可以访问和修改(损坏)该值?
静态变量与实例变量相比,没有什么本质上或多或少是线程安全的。但是您必须了解这些值是如何受到保护的以及 SingleThreadModel 是如何实现的。如果 SingleThreadModel 是通过允许 Servlet 的多个实例实现的,每个实例都停留在单个线程上,那么静态变量将在所有实例之间共享,因此它们的线程也可以访问。
无论如何,我认为您永远不应该在 Servlet 类中使用(非最终)静态变量,因为您无法控制 Servlet 的生命周期。它可以根据容器的需要被创建、销毁和重新创建。因此,当您下次尝试访问静态变量时,您放入的值可能不存在。而且你永远不应该使用 SingleThreadModel,因为它效率低下并且不能真正完成它的工作,而且它已经被弃用了很长时间。所以你绝对不应该同时使用它们。