全部,为了更好地理解Attributes
线程问题的HttpSession
。我为它编写了一些测试代码,我原以为下面的代码应该是线程安全的方法。
HttpSession session = request.getSession();
synchronized (session) {
Integer n = (Integer) session.getAttribute("foo");
session.setAttribute("foo", (n == null) ? 1 : n + 1);
}
但实际上它的Answer告诉我它不是。我只是无法理解它,在我看来,我认为会话是一个客户端和服务器之间的转换。这种情况是否存在任何线程问题?如果有,请告诉我在哪种情况下此代码不是线程安全的。感谢。
答案 0 :(得分:1)
AFAIK,没有什么能阻止servlet容器每次线程请求会话时返回不同的对象(即实际会话中的代理)。
如果容器这样做,在会话上同步将没有任何帮助,因为每个线程将在不同的对象上同步。
拥有线程安全计数器的最简单方法是使用AtomicInteger,并调用其增量方法之一,但这并不会阻止两个并发线程第一次存储AtomicInteger,如果它们都将其视为空。
确保最简单的方法(尽管可能不是最快)是使用全局锁来获取属性:
public static synchronized AtomicInteger getCounterFromSession(HttpSession session) {
AtomicInteger counter = (AtomicInteger) session.getAttribute("counter");
if (counter == null) {
counter = new AtomicInteger();
session.setAttribute("counter", counter);
}
return counter;
}
也就是说,在群集应用程序中,会话在群集的节点之间进行持久化或复制,因此也不会带来任何保证。将计数器存储在数据库中将是解决方案。