Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>So its been a few years since I've done anything with Java Servlets here so I'm going from memory.</p> <p>I would expect the thread safety problem here is in the check for cart==null. When looking at threading issues the thing one must understand is that a thread can be interrupted between ANY two machine instructions (not just any line of code). That is to say, that even</p> <pre><code>i += 1; </code></pre> <p>is not threadsafe (if i is shared anyways) as i += 1 is (at least) two instructions: an add, and a store. The thread can get interrupted between the add and the store and only one of the adds will survive. </p> <p>The same thing is occuring in this example. Suppose for a moment, two threads make a request on the same session (eg. as Goetz suggests from frames or ajax requests). One enters this code section, successfully retrieves the HttpSession, then attempts to get the "shoppingCart" attribute. However, since it does not yet exist, null is returned. The thread is then interrupted by another request which does the same thing. It also gets null. The two requests then proceed in any sequence, however, since both retreived a null reference for the "shoppingCart" attribute since the cart had not been stored at that time, both threads will create a new Cart object and both will try to store it. One will loose and those changes to the Cart will be lost. Thus this code is not threadsafe.</p> <p>As for the second half of your question, I am not familiar with the AtomicReference object. I quickly looked over the java API for AtomicReference and it might work, but I'm not sure. In any case. The most obvious solution I can think of here is to use a monitor. Basically what you're looking to do is have mutual exclusion on the get-test-set portion of your code.</p> <p>Now, provided your cart object is atomic (ie, we only need to protect the getting and setting of it, I think something like this could work:</p> <pre><code>public syncronized ShoppingCart atomicGetCart(HttpSession session){ ShoppingCart cart = (ShoppingCart)session.getAttribute("shoppingCart"); if (cart == null) { cart = new ShoppingCart(...); session.setAttribute("shoppingCart", cart); } return cart; } HttpSession session = request.getSession(true); ShoppingCart cart = atomicGetCart doSomethingWith(cart); </code></pre> <p>Now, I don't know much about the performance of Java monitors so I'm not sure what kind of overhead this would incur. Also, this would have to be the only location where cart is retrieved. Basically, the syncronized keyword means that only one thread can enter the method atomicGetCart at a time. A lock is used to enforce this (a lock is simply an object that can be owned by only one thread at a time). This way you no longer have the race condition that was in the other code.</p> <p>Hope this helps, -Daniel</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload