3 回答

TA贡献1872条经验 获得超3个赞
不,根据IBM- Java理论和实践,它们不是线程安全的:所有有状态的Web应用程序都损坏了吗?。您需要同步。
从Java Ranch来看HttpSession如何不是线程安全的,这也可能会有所帮助。

TA贡献1803条经验 获得超6个赞
Servlet 2.5规范:
执行请求线程的多个servlet可以同时主动访问同一会话对象。容器必须确保以线程安全的方式对表示会话属性的内部数据结构进行操作。开发人员负责对属性对象本身进行线程安全访问。这将保护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创建互斥体,但是必须有更好的方法。

TA贡献1865条经验 获得超7个赞
在某些方面,这取决于您的客户端设计。
在您的Web设计中,您是否有机会让单个客户端使用同一HTTP会话拥有多个未完成的同时请求?除非您将单个HTTP会话绑定到多个套接字,否则这似乎很难做到。(aka,AJAX)没有这样做,就服务器而言,给定客户端的HTTP访问将是单线程的,这意味着单个会话实际上是线程安全的。
会话对象的同步将使应用程序更安全,以防将来的更改使Web应用程序能够同时发出多个请求,因此这不是一个坏主意。在现代Java实现中,同步并没有以前带来的高昂成本,尤其是在通常不争用同步的情况下。如果您的应用程序使用AJAX,这意味着您希望向Web服务器发送多个正在进行的同时请求,那么必须进行同步。
添加回答
举报