HttpSession线程安全吗,set / get属性线程安全操作?
此外,被设置的对象是否必须是线程安全的,以确保我们知道存储在会话中的对象的状态是已知的。
另外,我正在网上阅读一些build议使用:
synchronized(session) { session.setAttribute("abc", "abc"); }
这是一个有效的build议?
不,根据IBM的Java理论和实践 ,它们不是线程安全的:所有有状态的Web应用程序都被破坏了吗? 。 你需要同步。
如何HttpSession不是从Java牧场线程安全也可能是有帮助的。
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来创build互斥锁 ,但必须有更好的方法。
没有。因为你不想让同一个客户端(有会话)在做并发请求,所以你应该像SpringControl MVC中的AbstractController那样序列化这些请求
在某些方面,这取决于您的客户devise。
在您的网页devise中,您是否有机会使用相同的HTTP会话为单个客户端提供多个未完成的同步请求? 这似乎很难做,除非你把一个HTTP会话绑定到多个套接字。 (aka,AJAX)就这样做而言,就服务器而言,给定客户端的HTTP访问将是单线程的,这意味着单个会话实际上是线程安全的。
会话对象的同步将使应用程序更安全,以防将来的更改使您的Web应用程序能够同时发出多个请求,所以这不是一个坏主意。 在现代的Java实现中,同步不会有以前与之相关的大量开销,特别是当同步通常是无人参与时。 如果您的应用程序使用AJAX,这意味着您希望多个同时向您的Web服务器发送请求,则必须同步。
他们不是,但大多数时候,你的客户只能通过一个线程访问他们。
不同的客户端会有不同的线程,每个客户端都有自己的会话。
正如Eddie所指出的那样,在两个线程访问同一个会话的情况下,两个Ajax调用正试图修改同一个会话属性。 否则你不会有问题。
会话不是线程安全的,既不保证设置的方法是线程安全的。 一般来说,在一个servlet容器中,你应该假设是在一个multithreading的环境中,没有提供的工具是安全的。
这也适用于您在会话中存储的对象。 会话本身不会操作存储的对象,但是您可以在不同的线程中检索对象并尝试操作它。 检查你自己的代码,看看是否有可能的竞争条件。
您发布的代码示例是有效的,但问题可能超出了示例的有限范围。 它确保在设置会话时没有任何条件,但是没有任何东西阻止其他线程覆盖该设置。 如果请求中的代码依赖于值保持不变,那么您仍然可能遇到麻烦。