-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256 Mark,
On 1/17/18 4:31 PM, Mark Thomas wrote: > On 17/01/18 17:05, Christopher Schultz wrote: >> All, >> >> I have a use-case related to caching where I need to make sure >> that an operation only happens one time with respect to an object >> in the session. Basically, I want to build a cache and put it >> into the session, but it needs to be thread-safe enough that two >> threads can't see the object isn't there, build such an object, >> and then put it into the session (thereby overwriting each >> other). >> >> This is not a theoretical problem... we are observing threads >> overwriting each other's caches in the session. >> >> The good news is that I only have to deal with a single >> container instance on a single server/JVM, so there is no concern >> about session replication or anything else like that. I also >> don't have to worry about the session being created/destroyed >> around the same time. >> >> The servlet API says that HttpServletRequest.getSession() returns >> an HttpSession object (well, an object implementing HttpSession), >> but makes no guarantees about its thread-safety (e.g. with >> respect to getAttribute/setAttribute calls), so I cannot >> guarantee anything about whether getAttribute/setAttribute calls >> will be safe, though they would really have to be otherwise the >> server would encounter all kinds of problems. > > [get|set]Attribute operate on a ConcurrentHashMap so they are > thread-safe Yeah, I figured that. Otherwise, multi-threading basically couldn't happen. I'm surprised the servlet spec doesn't formally guarantee this because practically speaking, it's a requirement. > but you still need to co-ordinate if multiple threads are trying to > write. Of course. >> That doesn't really matter because I need to do something like >> this: >> >> Cache myCache = null; synchronized (something) { myCache = >> session.getAttribute("cacheKey"); if(null == myCache) { myCache = >> new Cache(); session.setAttribute("cacheKey", cache); } } >> >> If I don't synchronize on a consistent monitor, there is a race >> condition between the "get" and the "set" between threads using >> the session. >> >> So the question is "what should I use as the monitor?" >> >> My first thought was that I should use the session object >> itself: >> >> Cache myCache = null; synchronized (session) { myCache = >> session.getAttribute("cacheKey"); if(null == myCache) { myCache = >> new Cache(); session.setAttribute("cacheKey", cache); } } >> >> That would be the best option, since it's the object I actually >> care about. However, I believe Tomcat sometimes (always) provides >> wrapper objects around servlet-spec-defined objects and I'm >> wondering if there are any guarantees about the HttpSession >> object being consistent across threads? >> >> That is, will Tomcat always give an identical object to two >> different threads whose requests are associated with the same >> session? Or are there cases where the two threads might get >> different objects? > > It should always be the same object. Looking at the code, I don't > see any obvious holes. > > For the record, relevant code includes: > o.a.catalina.connector.Request.getSession() > o.a.catalina.session.ManagerBase.createSession(String) > o.a.catalina.session.StandardSession.getSession() Could this be something we could formally guarantee (via documentation)? I'd like to lobby the servlet EG for the same guarantee, but getting it done in Tomcat is more immediately valuable for me :) - -chris -----BEGIN PGP SIGNATURE----- Comment: GPGTools - http://gpgtools.org Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ iQJRBAEBCAA7FiEEMmKgYcQvxMe7tcJcHPApP6U8pFgFAlpgsRkdHGNocmlzQGNo cmlzdG9waGVyc2NodWx0ei5uZXQACgkQHPApP6U8pFhZCw//REi7247L3Z03DyRq D/JTRgafh9yiuf5hMAT1TldPHmfSn0CS6dIA+BqNItCs1ESytgjufh3koqFwbIz0 YxAlXZf7A7Vy+tLdx+3GUHZJSdbgq7HmFnAX5ATnaLiXPYk/uLAHo1+fh1LKCvev Jn1CNCmPItY8nFMR6L/qiOvhRIfjgktez66+tyns+ECRvgya4fMF10FoqK7rEbuP P3M3UQ1AS6+fnf3BzkYbpjjkKT92nNwL1Nj0XFp8ucZgc3rmYGcfbtyneDfQc9VZ NumB5T5r6cJ1hyZuEkT16CD95l1XYe7aPbbWDB7sL1DBnXPVgs8hCyRlyG7ggYmo IYPIAqiAjsE8idLz+diUdr7TGe40qyfyQnFW8D2HCB34EnilieE6nUwNou1zTW3q pzFS38s3ZN9xAMK+gesoQcrvKRZe1w1I1HFCISykK1pKbphMrg7ay6SEnyp4OFz5 LylyH0I1ybQeh64zSsFyftNO+LVL6W5uxigrr0lS9p4njP65WHtD1EXX899WlfBP Cr3wLX9YOMv7I+t5jLxQktDrKmfk6MLA2cW1jbN18EdYv/IgEhmTgWiFXwbcUT02 d0fe0AtZ0HZjDc71GtZSA4TtrebjH+iRN7sTP8Ky1qcOiNjIcstay9MHbXrSyV5C uSPruAvm1TksxFVIpKx5saCyOeI= =fSBn -----END PGP SIGNATURE----- --------------------------------------------------------------------- To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org