此外,正在设置的对象是否必须是线程安全的,以保证我们知道会话中存储的对象的状态是什么。

另外,我正在网上阅读一些建议使用:

synchronized(session) {
  session.setAttribute("abc", "abc");
}

这是一个有效的建议吗?

有帮助吗?

解决方案

不,它们不是线程安全的,根据IBM的说法 - Java理论与实践:所有有状态的Web应用程序都已损坏吗?。你需要同步。

HttpSession如何不是线程安全的来自Java Ranch也可能会有所帮助。

其他提示

Servlet 2.5规范:

  

多个servlet正在执行请求   线程可以有活动访问权限   同一个会话对象。   容器必须确保   操纵内部数据   代表会话的结构   属性在a中执行   线程安全的方式。开发者有   线程安全的责任   访问属性对象   他们自己。这将保护   里面的属性集合   来自并发的HttpSession对象   访问,消除机会   用于导致该问题的应用程序   收集被破坏。

这是安全的:

// guaranteed by the spec to be safe
request.getSession().setAttribute("foo", 1);

这是安全:

HttpSession session = request.getSession();
Integer n = (Integer) session.getAttribute("foo");
// not thread safe
// another thread might be have got stale value between get and set
session.setAttribute("foo", (n == null) ? 1 : n + 1);

保证安全:

// no guarantee that same instance will be returned,
// nor that session will lock on "this"
HttpSession session = request.getSession();
synchronized (session) {
  Integer n = (Integer) session.getAttribute("foo");
  session.setAttribute("foo", (n == null) ? 1 : n + 1);
}

我已经看到了最后一种提倡的方法(包括在J2EE书籍中),但不保证它可以通过Servlet规范工作。您可以使用会话ID创建互斥锁,但必须有更好的方法。

没有。并且由于您不希望同一个客户端(使用会话)执行并发请求,您应该序列化这些请求,如 AbstractController 在Spring MVC中执行

在某些方面,这取决于您的客户端设计。

在网页设计中,您是否有机会让单个客户端使用相同的HTTP会话拥有多个未完成的同时请求?除非将单个HTTP会话绑定到多个套接字,否则这似乎很难做到。 (aka,AJAX)如果没有这样做,就服务器而言,给定客户端的HTTP访问将是单线程的,这意味着单个会话实际上是线程安全的。

会话对象的同步将使应用程序更安全,以防止将来的更改使您的Web应用程序能够同时拥有多个请求,因此这不是一个坏主意。在现代Java实现中,同步不具有先前与其相关联的大量成本,尤其是当同步通常是无竞争的时。如果您的应用程序使用AJAX,这意味着您希望同时向Web服务器发送多个请求,则必须进行同步。

它们不是,但大多数时候,您的客户只能通过一个线程访问它们。

不同的客户端将拥有不同的线程,每个客户端都有自己的会话。

正如Eddie所指出的,一种情况是你可能面临两个线程访问同一个会话,两个ajax调用正在尝试修改相同的会话属性。否则你不会有问题。

会话不是线程安全的,并且get和set set方法都不保证是线程安全的。通常,在servlet容器中,您应该假设处于多线程环境中,并且没有提供的工具是安全的。

这也适用于您在会话中存储的对象。会话本身不会操纵存储的对象,但您可以在不同的线程中检索该对象并尝试操作它。您可以自行检查自己的代码,看看是否有竞争条件。

您发布的代码示例有效,但问题可能超出您示例的有限范围。它确保在设置会话时没有条件,但没有任何东西阻止其他线程覆盖该集合。如果您的请求中的代码取决于保持不变的值,您仍可能遇到麻烦。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top