1

在处理 ASP.NET 应用程序时,我发现在会话缓存中放置一些东西,或者实际上,访问会话缓存中的变量会导致我的 Ajax 查询停止异步。我了解到这是因为会话基本上是阻塞的——如果我同时从浏览器发出两个 Ajax 请求,而第一个请求需要一点时间才能返回,则会话被锁定在第一个请求中,直到该请求完成,在这一点我的第二个 Ajax 请求开始工作。

在 PHP 中,我收集到有一个选项可以关闭会话以进行写入(和/或以只读方式打开它),以便会话变量访问是非阻塞的并且事情保持异步。

我正在构建一个将是 Java 的应用程序,可能在 Tomcat 上运行(尽管如果需要,我可以更改为其他容器)并且我无法确定 Java 是否有相同的问题(会话变量读取块)或有相同的补救措施(提前关闭,只读模式)。有没有人遇到过这个问题?

4

2 回答 2

2

在 Tomcat 中,HttpSessionorg.apache.catalina.session.StandardSession(source here ) 中实现。

如果您查看源代码,您会看到对 a 的调用HttpSession.getAttribute(String)几乎HttpSession.setAttribute(String, Object)没有ConcurrentHashMap 任何额外的同步。

这意味着这些调用派生了ConcurrentHashMap. 引用它的Javadoc

  • 检索操作不需要锁定,也不支持以阻止所有访问的方式锁定整个表。<..> 检索操作(包括get)一般不会阻塞,因此可能与更新操作(包括put和remove)重叠
  • 该表在内部进行了分区,以尝试允许指定数量的并发更新而不会发生争用。因为哈希表中的放置本质上是随机的,所以实际的并发性会有所不同。
于 2012-10-24T21:23:45.557 回答
0

看起来阻塞是由于线程同步访问而发生的HttpSession,如this SO answer中所述

因此,必须是第二个请求仅在第一个请求正在使用时才被阻止HttpSession(或者如果您有一些由第一个请求长时间持有的共享锁,但这与 Tomcat 无关)。

由于 Servlets 规范要求此同步,因此您不应尝试违反它。相反,让您的应用程序尽量减少读取或写入HttpSession.

此外,正如我在上面所写的,如果您有额外的锁使多个请求按顺序执行,则可能会发生阻塞。当您向 Tomcat 发送第二个请求时,尝试对 Tomcat 进行多个线程转储,并查看是否有任何此类锁正在等待第二个请求。

于 2012-10-24T21:21:31.113 回答