此外,正在设置的对象是否必须是线程安全的,以保证我们知道会话中存储的对象的状态是什么.
此外,我正在网上阅读一些建议使用:
synchronized(session) { session.setAttribute("abc", "abc"); }
这是一个有效的建议吗?
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创建互斥锁,但必须有更好的方法.
不,它们不是线程安全的,根据IBM - Java理论和实践:所有有状态的Web应用程序都被破坏了吗?.你需要同步.
HttpSession如何不受Java Ranch的线程安全可能也有帮助.