当前位置: 首页 > 面试题库 >

HttpSession中的同步可行吗?

徐安康
2023-03-14
问题内容

更新: 问题后的解决方案。

通常,同步是在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) {
  ...
}

对这个解决方案有什么意见吗?


问题答案:

我在spring-mvc
JavaDoc中找到了以下很好的解释WebUtils.getSessionMutex()

在许多情况下, HttpSession引用本身也是一个安全的互斥体 ,因为对于同一活动的逻辑会话,它始终是相同的对象引用。但是,
不能保证在不同的servlet容器之间都能做到这一点 ;唯一的100%安全方法是会话互斥。

synchronizeOnSession设置标志时,此方法用作锁定:

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

如果您查看的实现getSessionMutex(),它实际上会使用一些自定义会话属性(如果存在)(在org.springframework.web.util.WebUtils.MUTEX键下),或者使用HttpSession实例(如果没有):

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

回到简单的Servlet规范-要100%确保使用自定义会话属性,而不是HttpSession对象本身。

也可以看看

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


 类似资料:
  • 问题内容: 我想完全消除HttpSession- 我可以在web.xml中这样做吗?我敢肯定,有一些特定于容器的方法可以做到这一点(当我进行Google搜索时,搜索结果会很拥挤)。 PS这是个坏主意吗?在我真正需要它们之前,我宁愿完全禁用它们。 问题答案: 我想彻底消除HttpSession 您不能完全禁用它。您需要做的就是 不要 在Web应用程序的代码中任何地方或任何地方都得到它的句柄,并确保您

  • 是否可以调用一个异步方法,以便它从一个同步的方法异步运行?我不关心它挂起同步调用程序直到它返回,而是希望该方法被异步调用。

  • 问题内容: 我想完全消除HttpSession-我可以在web.xml中这样做吗?我敢肯定,有一些特定于容器的方法可以做到这一点(当我进行Google搜索时,这会挤满搜索结果)。 PS这是个坏主意吗?在我真正需要它们之前,我宁愿完全禁用它们。 问题答案: 我想彻底消除HttpSession 您不能完全禁用它。您所需要做的就是不要在Web应用程序的代码中任何地方)或任何地方获取它的句柄,并确保您的J

  • 问题内容: 我正在查看包含同步方法的第三方库中的一些代码,在此方法中,有一个锁定在实例变量上的同步块。与此类似: 这有意义吗?如果是这样,在同步方法中使用同步语句有什么好处? 鉴于同步方法锁定了整个对象,对我来说似乎是多余的。在使用非私有的实例变量时,这种方法是否有意义? 问题答案: 在您的示例中,该方法 同时 锁定了和的实例。其他方法可能仅锁定对象的实例 或 对象。 因此,是的,这完全取决于他们

  • 问题内容: 我已经编写了一个JavaScript函数,该函数使用XmlHttpRequest异步调用Web服务。我被要求使此功能在呈现页面之前完成其工作。 我以为我可以使AJAX请求同步,但是我不希望这使页面挂起太长-如果没有收到响应,我想在1秒后中止请求。 是否可以中止同步的XmlHttpRequest? 问题答案: 您不能: http://www.hunlock.com/blogs/Snipp

  • 一旦遇到这样的问题,这里还有更多内容,然后发现了 一个适当恶劣的解决方法。 这篇文章没有列在索引中,但是为满足你的好奇心而保留了下来。