HttpSession 中的同步是否可行?
更新:问题后立即解决.
通常,同步是在 JVM 中序列化并行请求,例如
Usually, synchronization is serializing parallel requests within a JVM, e.g.
private static final Object LOCK = new Object();
public void doSomething() {
...
synchronized(LOCK) {
...
}
...
}
在查看 Web 应用程序时,JVM global"上的一些同步范围可能成为性能瓶颈,并且仅在用户的 HttpSession 会更有意义.
When looking at web applications, some synchronization on "JVM global" scope is maybe becoming a performance bottleneck and synchronization only within the scope of the user's HttpSession would make more sense.
下面的代码有可能吗?我怀疑在会话对象上同步是一个好主意,但听听您的想法会很有趣.
Is the following code a possibility? I doubt that synchronizing on the session object is a good idea but it would be interesting to hear your thoughts.
HttpSession session = getHttpServletRequest().getSession();
synchronized (session) {
...
}
关键问题:
对于处理来自同一用户的请求的所有线程,是否保证会话对象是相同的实例?
似乎会话对象本身并不总是相同,因为它取决于 servlet 容器(Tomcat、Glassfish 等)的实现,并且 getSession()
方法可能只返回一个包装器实例.
It seems that the session object itself is not always the same as it depends on the implementation of the servlet container (Tomcat, Glassfish, ...) and the getSession()
method might return just a wrapper instance.
因此建议使用存储在会话中的自定义变量作为锁定对象.
这是我的代码建议,欢迎反馈:
Here is my code proposal, feedback is welcome:
在 Helper 类中的某处,例如我的助手
:
somewhere in a Helper Class, e.g. 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;
}
然后你就可以使用它了:
and then you can use it:
Object sessionLock = MyHelper.getSessionLock(getRequest(), null);
synchronized (sessionLock) {
...
}
对此解决方案有何评论?
Any comments on this solution?
推荐答案
这是我自己的解决方案:
似乎会话对象本身并不总是相同,因为它取决于 servlet 容器(Tomcat、Glassfish 等)的实现,并且 getSession()
方法可能只返回一个包装器实例.
Here is my own solution:
It seems that the session object itself is not always the same as it depends on the implementation of the servlet container (Tomcat, Glassfish, ...) and the getSession()
method might return just a wrapper instance.
因此建议使用存储在会话中的自定义变量作为锁定对象.
这是我的代码建议,欢迎反馈:
Here is my code proposal, feedback is welcome:
在 Helper 类中的某处,例如我的助手
:
somewhere in a Helper Class, e.g. 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;
}
然后你就可以使用它了:
and then you can use it:
Object sessionLock = MyHelper.getSessionLock(getRequest(), null);
synchronized (sessionLock) {
...
}
对此解决方案有何评论?
Any comments on this solution?
相关文章