2

Regarding HTTPSession, I am using Java Servlets and no framework. I have read about AtomicReferences but am not clear how I can use this to make this code thread safe. Am I correct in assuming I can simply mark updateSessionHashSet synchronized in providing safety? I understand this is not recommended for being inefficient. What other options and syntax is there?

Inside HTTPServlet:

private void updateSessionHashSet(HttpServletRequest req){
  HashSet<String> hs = req.getSession().getAttribute("theHashSet");
  String csv = req.getParameter("theCsv");

  String[] arr = csv.split(",");
  for(int i = 0; i < arr.length; i++){
      hs.add(arr[i].trim());
  }
}

public void doPost(HttpServletRequest  req,HttpServletResponse res) throws IOException {
   updateSessionHashSet(req);
}
runtim23
  • 38
  • 5
  • 2
    There is nothing to protect in the code you provided. Local variables are thread-safe. – J-Alex Feb 01 '19 at 15:50
  • 1
    Your question reveals a large lack in the understanding of thread safety. You do not seem to know what thread safety is for and when and what to synchronize. Answering that is far beyond the provided question. So I marked your question as too broad. – Seelenvirtuose Feb 01 '19 at 16:02
  • the function has no state,it is a thread safe method – TongChen Feb 01 '19 at 16:02
  • I understand basic thread safety in the Java language but not in JEE. I'm confused as to why topics such as https://stackoverflow.com/questions/616601/is-httpsession-thread-safe-are-set-get-attribute-thread-safe-operations this one exist. I don't see any state in these questions yet they are declared as unsafe. If I am lacking understanding to discuss on this topic is there a recommended resource to acquire better understanding? The manuals I've read our very vague with no code examples. – runtim23 Feb 01 '19 at 16:15
  • Update your question with the information from comment, because it's barely understandable from original post that you're trying to achieve thread-safety for a session. – J-Alex Feb 01 '19 at 16:37

2 Answers2

1

The posts you're referencing are telling you that the HTTPSession is shared state and you have to be careful when multiple threads can modify it. Here the opportunity for threads to interfere is if somehow you have two concurrent POSTs from the same user that call this method. You can handle it by something like

private void updateSessionHashSet(HttpServletRequest req){
    String csv = req.getParameter("theCsv");
    Set<String> hs = new HashSet<String>();
    String[] arr = csv.split(",");
    for(int i = 0; i < arr.length; i++){
        hs.add(arr[i].trim());
    }
    req.getSession().setAttribute("theHashSet", hs);
}

This way you put together the new hashset in a local variable first, then the code overwrites the reference to the session's theHashSet attribute atomically. If two threads are calling the same code then one or the other will win, but the two won't be jumbled together (which it seems like could happen with your posted code).

Alternatively you could so like some of the answers on the linked posts advise and synchronize on the HttpSession object, but since you're synchronizing on a Java object that is local to that instance of the application, you have to look out for the case where the application is distributed across several nodes. Synchronization means using a shared lock, and across JVMs there's no sharing.

It's really common for IT departments to want to deploy an application to several instances to avoid having a single-point-of-failure. You can deal with the synchronization problem by pinning the session to a specific server, but that makes load-balancing hard.

By the way stashing stuff in the HttpSession probably isn't the best plan, you should save this in some kind of data store. The best way to have safe concurrency is to minimize the amount of mutable state. The HttpSession is not something to use as long-term storage.

For guidelines about thread-safety of Java EE stuff, I have a related answer here.

Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276
  • This touches on the set after write mentioned in the IBM article from my link though there are still issues. For one, this overwrites the hashset losing my previously stored data and two, if you do reuse the mutable data and immediately pass it to setAttribute to replicate changed data back to the session then you haven't really fixed anything? I also understood this to only be vulnerable from the same session but wanted more clarity. Regardless, your provided answers have provided sufficient understanding better focus for further studies. I also appreciate your real world considerations. – runtim23 Feb 01 '19 at 17:10
  • @timdedrick: if you mean you want to merge your data with pre-existing stuff then yes, that's a lot more work. really the httpsession is probably a really awkward place to try to store things, there are much better options, including keeping it in the browser until you can save it to a permanent serverside datastore. – Nathan Hughes Feb 01 '19 at 17:54
0

You should care about thread-safety when you have shared mutable members in your class.

Local variables are stored in each thread's own stack so local variables never shared between threads. The same related to local primitive variables.

Case 1, local thread-safe primitive:

class Processor {
    public void threadSafeMethod() {
         int count = 0;
         count++;
    }
}

Local references to objects are more complicated. The reference itself is not shared. The object referenced however, is stored in the shared heap.

If an object created locally never escapes the method, it is thread-safe.

Case 2, local thread-safe reference:

class Processor {
    public void threadSafeMethod() {
         StringBuilder sb = new StringBuilder("Text");
         appendPoint(sb);
    }

    public void appendPoint(StringBuilder b) {
         b.append(". ");
    }
}

Case 3 non-thread-safe shared mutable members:

class Processor {

    private StringBuilder sb; // shared mutable reference

    public void nonThreadSafeMethod() {
         sb = new StringBuilder("Text");
         appendPoint(sb);
    }

    public void appendPoint(StringBuilder b) {
         b.append(". ");
    }
}

Case 4 thread-safe shared immutable members:

class Processor {
    private String s; // shared immutable reference

    public void threadSafeMethod(final String str) {
         s = str; // Thread-safe because immutable
    }
}
J-Alex
  • 6,881
  • 10
  • 46
  • 64
  • Thank you. Well presented and explained, however, this did not answer my question since the examples you provide are somewhat blackboxed until exploring the JEE source code. – runtim23 Feb 01 '19 at 16:51