Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using request.getSession() as a locking object?

I have some java code that gets and sets a session attribute:

Object obj = session.getAttribute(TEST_ATTR);
if (obj==null) {
  obj = new MyObject();
  session.setAttribute(obj);
}

In order to make this code thread-safe, I'd like to wrap it in a synchronized block. But what do I use as the locking object? Does it make sense to use the session?

synchronized (session) {
  Object obj = session.getAttribute(TEST_ATTR);
  if (obj==null) {
    obj = new MyObject();
    session.setAttribute(obj);
  }
}
like image 214
MCS Avatar asked Nov 30 '09 15:11

MCS


People also ask

What is the use of getSession ()?

getSession() returns the valid session object associated with the request, identified in the session cookie that is encapsulated in the request object. Calling the method with no arguments creates a session if one does not exist that is associated with the request.

What is request getSession () setAttribute?

When you use request. getSession(). setAttribute() , you store something for that particular user session. You can use this attribute whenever you want if the user session has not expired.

Which interface defines getSession () method?

The HttpServletRequest interface provides two methods to get the object of HttpSession: public HttpSession getSession():Returns the current session associated with this request, or if the request does not have a session, creates one.

Is HTTP session thread safe?

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.


3 Answers

It is generally frowned upon to use a lock that you have no control over. A lock should be scoped as tightly as possible and since the session is more or less a global object, it does not fit the bill. Try to use a separate lock from the java.util.concurrent.locks package and scope it to your class.

like image 62
Kevin Avatar answered Nov 29 '22 20:11

Kevin


In the context of servlets? Servlets can be distributed across multiple processes, therefore you can't always have the same session object. A corollary to this is that a servlet container may decide to give you a different session object in the same process.

IIRC, Brian Goetz wrote an interesting article on the difficulty of doing things right with sessions.

My advice: Stay clear of sessions as much as possible, and don't lock random objects (use a lock object that has no other purpose).

like image 34
Tom Hawtin - tackline Avatar answered Nov 29 '22 22:11

Tom Hawtin - tackline


I took a look at the article you posted. You could skip synchronizing all together and take the same approach that the author did by using compare-and-set to ensure that your data is correct:

ServletContext ctx = getServletConfig().getServletContext();
AtomicReference<TYPE> holder 
    = (AtomicReference<TYPE>) ctx.getAttribute(TEST_ATTR);
while (true) {
    TYPE oldVal = holder.get();
    TYPE newVal = computeNewVal(oldVal);
    if (holder.compareAndSet(oldVal, newVal))
        break;
} 

holder.compareAndSet(old, new) will return false if some other thread updated the value of "holder" since you last read it. holder.compareAndSet(,) is put in a while(true) loop so that if the value did change before you were able to write it then you get a chance to read the value again and re-try your write.

http://java.sun.com/javase/6/docs/api/java/util/concurrent/atomic/AtomicReference.html

like image 41
Matt Wonlaw Avatar answered Nov 29 '22 21:11

Matt Wonlaw