1

参考:Head First Servlets & JSP, page 204, 第三题:

问:“实现 SingleThreadModel 的效果实际上与同步服务方法的效果相同。两者都可以在不保护会话和上下文状态的情况下使 Web 应用程序瘫痪。”

这是什么意思:“在不保护会话和上下文状态的情况下让 Web 应用程序崩溃”?他们是说实现 SingleThreadModel 不够线程安全吗?因为即使一次只能在一个 servlet 上运行一个线程,这不会阻止其他 servlet 访问和改变上下文/会话范围的变量吗?如果 Servlet 实现了 SingleThreadingModel,那么为什么需要保护会话状态?它一次只允许一个线程。我认为,即使您打开一个新的浏览器窗口,servlet 也不允许您发出两个请求。也许它们意味着不同的 Servlet 一次只有一个线程,如果它们不同步该状态,它们仍然可能破坏上下文/会话状态?

为什么类(静态)变量不是线程安全的?因为所有线程都可以访问和修改(损坏)该值?

对我来说还是有点模糊。

4

3 回答 3

4

参考: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,因为它效率低下并且不能真正完成它的工作,而且它已经被弃用了很长时间。所以你绝对不应该同时使用它们。

于 2013-07-23T10:00:11.523 回答
1

让 Web 应用程序崩溃

因为对service()Servlet的方法的访问会被同步。这可以通过两种方式实现,(1)阻塞其他request线程直到当前线程完成执行service()(2)service()在容器中创建新的 Servlet 实例(或维护一个 Servlet 实例池)并且每个请求调用一个单独的实例。两者都是资源密集型和非高性能的。

不保护会话和上下文状态

因为即使您同步访问service()实现SingleThreadModel. 访问sessioncontext不同步。您的 Servlet 以外的代码可以自由访问HttpSessionServletContext属性。

他们是说实现 SingleThreadModel 不够线程安全吗?

是的,即使类变量也可能不是线程安全的,如果容器实现模型使得每个线程都使用池中的空闲 Servlet 实例。

因为即使一次只能在一个 servlet 上运行一个线程,这不会阻止其他 servlet 访问和改变上下文/会话范围的变量吗?

绝对地。

如果 Servlet 实现了 SingleThreadingModel,那么为什么需要保护会话状态?

为了保护存储在HttpSession. 因为即使一次只能在一个 servlet 上运行一个线程,这也不会阻止其他 servlet 访问和改变上下文/会话范围的变量。

类(静态)变量不是线程安全的

因为它由一个类的所有实例共享。

于 2013-07-23T09:49:01.670 回答
0

为什么类(静态)变量不是线程安全的?因为所有线程都可以访问和修改(损坏)该值?

正确的。如果成员是静态的,则一个线程可以设置一个值,而另一个线程可以设置不同的值。由于静态是共享变量,因此第一个线程设置的值对于另一个线程也将相同。

问:“实现 SingleThreadModel 的效果实际上与同步服务方法的效果相同。两者都可以在不保护会话和上下文状态的情况下使 Web 应用程序瘫痪。”

即使您实现了一些 servlet 实现SingleThreadModel,它也只会停止那些试图访问该 servlet 的线程同时执行。它不能阻止所有其他未实现SingleThreadModel的 servlet 访问上下文和会话属性。这是因为上下文属性在整个 Web 应用程序中都可用,任何资源都可以访问和修改它们。

于 2013-07-23T09:41:46.997 回答