我看到很多关于HttpSession
上的setAttribute和getAttribute方法是否是原子的问题。他们不是。但是,每个客户实际调用request.getSession(true)
原子?
例如,如果您有一个servlet过滤器并且客户端发出两个同时到达行request.getSession(true)
的同时调用,则会返回相同的会话对象吗?我假设这样的东西会特定于容器吗?或者您是否为每个请求客户端进行了同步getSession
呼叫。
答案 0 :(得分:5)
不,不是。
Servlet规范说......
2.3.3.4线程安全 除了startAsync和complete方法之外,请求和响应对象的实现不保证是线程安全的。这意味着它们应该只在请求处理线程的范围内使用,或者应用程序必须确保对请求和响应对象的访问是线程安全的。
如果应用程序创建的线程使用容器管理的对象(例如请求或响应对象),则必须仅在对象的生命周期内访问这些对象,如3.10和5.6节中所定义。 b>请注意,除了startAsync和完整方法之外,请求和响应对象都不是线程安全的。如果在多个线程中访问这些对象,则应该同步访问或通过包装器完成访问以添加线程安全例如,同步方法的调用以访问请求属性,或者在线程内使用本地输出流作为响应对象。
还有你的问题? 对getSession的两个并发调用是否可能返回不同的HttpSession对象,即使它们来自同一个客户端? 答案是“是的,
答案 1 :(得分:1)
不确定你真正担心的是什么:
例如,如果您有一个servlet过滤器,并且客户端发出两个 同时到达该线路的同时呼叫:
request.getSession(true)
会返回相同的会话对象吗?
这取决于同一会话对象的含义,即,如果您的意思是s1 == s2
或s1.equals(s2)
。我找不到任何说明该对象必须相同(==
)的内容,但即使它们可能都是不同的对象,它们最终可以看到相同的逻辑< / em>会话。想象一下这些会话对象作为数据库客户端:它们不是数据,但它们都查看相同的数据,即它们读取和写入公共位置。
现在,为了回答您的问题,我们必须在从同一服务器读取任何其他响应之前决定客户端是否发出了第二个请求:必须使用一段输入(在URL或HTTP头中)跟踪会话,以cookie的形式),所以我们有以下场景:
所以这根本不是线程的问题。它只取决于客户端提供的输入。相同的会话ID,返回相同的会话。不同(或没有)会话ID,不同会话。
为了正确起见,逻辑客户端(单个程序,如Firefox)甚至可以在N +核心机器上的N个独立线程中发出N个请求,但网络通常是共享的。假设它有一个多宿主机器,并且每个NIC连接到一个单独的网络,您将需要您的servlet容器来侦听多个IP地址并拥有N个处理器(或核心)。这只是说没有必要同时进行两次同时调用,尽管来自同一客户端的请求完全可以并行处理,从而在同一时刻到达同一行。
答案 2 :(得分:0)
API中没有任何内容表明该方法已同步,但我不知道该方法内部发生了什么。如果不存在,则执行getSession(true)
会返回新会话。检查现有会话和创建新会话是您的关键部分。如果您的线程同时达到了这个,那么将创建两个会话并返回到您的两个不同的调用实体(过滤器将在您的servlet之前和之后应用,因此我不知道如何执行此操作,但是为了这个问题,让我们假设它可以发生)。如果Session
对象已存在,则只返回该对象。