1

All, For better understanding the Attributes of HttpSession thread issue.I wrote some test code for it ,I had thought the below code should be thread-safety way to go.

HttpSession session = request.getSession();
synchronized (session) {
  Integer n = (Integer) session.getAttribute("foo");
  session.setAttribute("foo", (n == null) ? 1 : n + 1);
}  

But Actually the Answer of it tell me It is not . I just can't understand it ,In my opinion, I thought the session is the conversion between one client and the server .Is there any thread issue for this situation? If there is , Please tell me in which case this code is not thread-safety. thanks.

Community
  • 1
  • 1
Joe.wang
  • 11,537
  • 25
  • 103
  • 180

1 Answers1

1

AFAIK, nothing prevents the servlet container to return a different object each time a thread asks for the session (i.e. a proxy over the real, actual session).

If the container does that, synchronizing on the session won't be of any help, since each thread will synchronize on a different object.

The easiest way to have a thread-safe counter is to use an AtomicInteger, and call one of its increment methods, but that doesn't prevent two concurrent threads from storing an AtomicInteger for the first time if they both see it as null.

The easiest way to be sure (although probably not the fastest) is to use a global lock to get the attribute:

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;
}

That said, in a clustered application, the session is made persistent or replicated across nodes of the clustered, so that doesn't bring any guarantee either. Storing the counter in the database would be the solution here.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • Thanks. your answer is very informative, Is there any possible exist concurrent request for the same session ? – Joe.wang May 04 '13 at 12:26
  • 1
    Yes, two requests for the same session can be handled concurrently. – JB Nizet May 04 '13 at 12:28
  • In your opinion, I think `synchronized(getServletContext())` will not any help to the it too. Because the `ServletContext` instance is different between the cluster nodes. right ? thanks. – Joe.wang May 04 '13 at 13:03
  • 1
    synchronizing on the servlet context would be the same as synchonizing on a class of your webapp, except you're not sure two threads share the same servlet context. So it has the same problem as synchronizing on the session. The container could return a different instance to each thread. And ever solution based on synchronization indeed doesn't work in case the application is clustered. – JB Nizet May 04 '13 at 13:40
  • +2 Yes, Thanks your verify. – Joe.wang May 04 '13 at 15:45