views:

2854

answers:

7

Also, does the object that is being set have to be thread safe in order to guarantee that we know what the state of the object stored in session is known.

Also, I was reading on the web that some suggest using:

synchronized(session) {
  session.setAttribute("abc", "abc");
}

Is this a valid suggestion?

+2  A: 

No, they are not thread safe, according to IBM. You need to synchronize.

This from Java Ranch might be helpful, too.

duffymo
Must read links! ++
cherouvim
Why would you like to synchronize them? There is one session per client and clients are single threaded isn't?
OscarRyz
@Oscar Reyes: A client can issue many concurrent requests. e.g CTRL+CLICKing (on firefox) like crazy on the stackoverflow logo.
cherouvim
@cherouvim: I see the point.
OscarRyz
@Oscar Reyes: Clients using AJAX can indeed have multiple requests to the same server open at a time.
Eddie
Yea, I knew they weren't thread safe. That much I know, but I was curious how to resolve the situation and how bad is it.Thanks for the info.
Berlin Brown
You don't necessarily need to synchronize, look at AtomicReference and the article...
Jon
+3  A: 

No. And since you don't want the same client (with session) to be doing concurrent requests, you should serialize these requests like they do in Spring MVC

cherouvim
I liked the example but still a little confused on how I would use this for my application.
Berlin Brown
A: 

In some ways, this depends on your client design.

Do you have the opportunity, in your web design, for a single client to have multiple outstanding simultaneous requests using the same HTTP session? This seems difficult to do unless you tie a single HTTP session to multiple sockets. (aka, AJAX) Short of doing this, a given client's HTTP access will be single-threaded as far as the server is concerned, which means a single session is effectively Thread safe.

Synchronization of your session objects will make the application safer against future changes that make your web application capable of having multiple simultaneous requests, so it's not a bad idea. In modern Java implementations, synchronization does not have the large cost that was previously associated with it, especially when the synchronization is usually uncontended. If your application uses AJAX, which implies that you expect multiple in-flight simultaneous requests to your web server, then synchronization is a must.

Eddie
I was just thinking about disabling "synchronizeOnSession" for ajax requests to speed things up (ajax requests are executing one after another, not in parallel). So it is a big no no then? I thought it is safe for ajax because work flow is usually controlled on javascript side anyway.
serg
A: 

The session is not thread safe and neither the get not the set methods are guaranteed to be thread safe. In general in a servlet container you should assume to be in a multi threaded environment and no provided tooling is safe.

This also goes for the objects you store in the session. The session itself will not manipulate the stored object but you can retrieve the object in different thread and attempt to manipulate it. It is up to you to examine your own code to see if race conditions are possible.

The code example you posted is valid, but the problem may exist beyond the limited scope of your example. It assures there are no conditions while setting to the session, but there is nothing preventing an other thread to override the set. If the code in your request depends of the value remaining unchanged you could still be in trouble.

DefLog
+12  A: 

Servlet 2.5 spec:

Multiple servlets executing request threads may have active access to the same session object at the same time. The container must ensure that manipulation of internal data structures representing the session attributes is performed in a threadsafe manner. The Developer has the responsibility for threadsafe access to the attribute objects themselves. This will protect the attribute collection inside the HttpSession object from concurrent access, eliminating the opportunity for an application to cause that collection to become corrupted.

This is safe:

// guaranteed by the spec to be safe
request.getSession().setAttribute("foo", 1);

This is not safe:

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

This is not guaranteed to be safe:

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

I have seen this last approach advocated (including in J2EE books), but it is not guaranteed to work by the Servlet specification. You could use the session ID to create a mutex, but there must be a better approach.

McDowell
@McDowell : Trying to understand what "The container must ensure that manipulation of internal data structures representing the session attributes is performed in a threadsafe manner" means. Doesn't it mean that a container like 'tomcat' is supposed to make sure that the getAttribute and setAttribute methods are thread safe ? Also, why is the last approach not guaranteed to work?
letronje
@letronje - this means that individual calls to getAttribute/setAttribute must be threadsafe, but no transactional guarantees are made for the servlet. So, concurrent use of the same session may result in inconsistent state unless the servlet developer protects against that.
McDowell
@letronje - the last approach requires that the session synchronizes on `this`. That is, has a signature like `public syncrhonized void setAttribute...` or `...setAttribute(String s,Object o) { synchronized(this)...`. The spec does not require this. Some servlet containers do this, but there are no guarantees - how the container protects the internal state is an implementation detail.
McDowell
@McDowell: So just to clarify, If there are two parallel requests under the same session and if one thread does request1.getSession().getAttribute("abc") and the other one does a request2.getSession().setAttribute("abc"), this should be fine ?
letronje
@letronje - in hindsight, my examples were poor. I've edited the post with code I hope demonstrates the problem. You may also find this question helpful: http://stackoverflow.com/questions/1820629/using-request-getsession-as-a-locking-object
McDowell
A: 

They are not, but most of the times, your clients will only access them with a single thread.

Different clients will have different threads and each one will have its own Session.

As Eddie points out, one situation where you may face two thread accessing the same session is two ajax calls are attempting to modify the same session attribute. Otherwise you won't have problems.

OscarRyz
A: 

Actually my answer is another question so I posted it here.

ceggers