HttpSession中的同步是否可行? [英] Is synchronization within an HttpSession feasible?

查看:108
本文介绍了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全局范围内的某些同步可能正在变为性能瓶颈和同步仅在用户的 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类的某个地方,例如 MyHelper

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;
}

然后你可以使用它:

Object sessionLock = MyHelper.getSessionLock(getRequest(), null);
synchronized (sessionLock) {
  ...
}

对此解决方案有何评论?

Any comments on this solution?

推荐答案

我在 spring-mvc JavaDoc for WebUtils.getSessionMutex()

I found this nice explanation in spring-mvc JavaDoc for WebUtils.getSessionMutex():


在许多情况下, HttpSession引用本身是一个安全的互斥锁同样,因为它始终是同一个活动逻辑会话的相同对象引用。但是,不能保证不同的servlet容器;唯一100%安全的方式是会话互斥。

In many cases, the HttpSession reference itself is a safe mutex as well, since it will always be the same object reference for the same active logical session. However, this is not guaranteed across different servlet containers; the only 100% safe way is a session mutex.

synchronizeOnSession <时,此方法用作锁定/ code>标志已设置:

This method is used as a lock when synchronizeOnSession flag is set:

Object mutex = WebUtils.getSessionMutex(session);
synchronized (mutex) {
    return handleRequestInternal(request, response);
}

如果你看一下 getSessionMutex()的实现,它实际上使用了一些自定义会话属性(如果 org.springframework.web.util.WebUtils.MUTEX 键)或 HttpSession 实例如果不是:

If you look at the implementation of getSessionMutex(), it actually uses some custom session attribute if present (under org.springframework.web.util.WebUtils.MUTEX key) or HttpSession instance if not:

Object mutex = session.getAttribute(SESSION_MUTEX_ATTRIBUTE);
if (mutex == null) {
    mutex = session;
}
return mutex;

返回普通servlet规范 - 100%确定使用自定义会话属性而不是 HttpSession 对象本身。

Back to plain servlet spec - to be 100% sure use custom session attribute rather than HttpSession object itself.

  • http://www.theserverside.com/discussions/thread.tss?thread_id=42912

这篇关于HttpSession中的同步是否可行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆