在 HttpSession 内进行同步是否可行?问题:总结答案/解决方案:另请参见
更新:问题后立即解决。
问题:
通常,同步是序列化JVM中的并行请求,例如
private static final Object LOCK = new Object();
public void doSomething() {
...
synchronized(LOCK) {
...
}
...
}
在查看Web应用程序时,“JVM全局”范围内的某些同步可能会成为性能瓶颈,并且仅在用户的HttpSession范围内进行同步会更有意义。
以下代码是否可行?我怀疑在会话对象上进行同步是一个好主意,但听到您的想法会很有趣。
HttpSession session = getHttpServletRequest().getSession();
synchronized (session) {
...
}
关键问题:
是否保证会话对象对于处理来自同一用户的请求的所有线程都是同一实例?
总结答案/解决方案:
似乎会话对象本身并不总是相同的,因为它依赖于servlet容器(Tomcat,Glassfish等)的实现,并且该方法可能只返回一个包装器实例。getSession()
因此,建议使用存储在会话中的自定义变量作为锁定对象。
这是我的代码建议,欢迎反馈:
在帮助器类中的某个位置,例如:MyHelper
private static final Object LOCK = new Object();
public static Object getSessionLock(HttpServletRequest request, String lockName) {
if (lockName == null) lockName = "SESSION_LOCK";
Object result = request.getSession().getAttribute(lockName);
if (result == null) {
// only if there is no session-lock object in the session we apply the global lock
synchronized (LOCK) {
// as it can be that another thread has updated the session-lock object in the meantime, we have to read it again from the session and create it only if it is not there yet!
result = request.getSession().getAttribute(lockName);
if (result == null) {
result = new Object();
request.getSession().setAttribute(lockName, result);
}
}
}
return result;
}
然后你可以使用它:
Object sessionLock = MyHelper.getSessionLock(getRequest(), null);
synchronized (sessionLock) {
...
}
对此解决方案有何评论?