Java HttpSession 线程安全,set/get 属性线程安全操作吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/616601/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 17:00:26  来源:igfitidea点击:

Is HttpSession thread safe, are set/get Attribute thread safe operations?

javasessionthread-safetysynchronized

提问by Berlin Brown

Also, does the object that is being set have to be thread safe in order to guarantee that we know what the state of the object stored in session is known.

此外,正在设置的对象是否必须是线程安全的,以确保我们知道会话中存储的对象的状态是已知的。

Also, I was reading on the web that some suggest using:

另外,我在网上阅读有些人建议使用:

synchronized(session) {
  session.setAttribute("abc", "abc");
}

Is this a valid suggestion?

这是一个有效的建议吗?

采纳答案by duffymo

No, they are not thread safe, according to IBM - Java theory and practice: Are all stateful Web applications broken?. You need to synchronize.

不,它们不是线程安全的,根据 IBM - Java 理论和实践:所有有状态的 Web 应用程序都被破坏了吗?. 你需要同步。

How HttpSession is not thread safefrom Java Ranch might be helpful, too.

HttpSession 如何不是Java Ranch 的线程安全也可能会有所帮助。

回答by cherouvim

No. And since you don't want the same client (with session) to be doing concurrent requests, you should serialize these requests like the AbstractControllerdoes in Spring MVC

不。而且由于您不希望同一个客户端(带有会话)进行并发请求,您应该像AbstractController在 Spring MVC 中所做的那样序列化这些请求

回答by Eddie

In some ways, this depends on your client design.

在某些方面,这取决于您的客户端设计。

Do you have the opportunity, in your web design, for a single client to have multiple outstanding simultaneous requests using the same HTTP session? This seems difficult to do unless you tie a single HTTP session to multiple sockets. (aka, AJAX) Short of doing this, a given client's HTTP access will be single-threaded as far as the server is concerned, which means a single session is effectively Thread safe.

在您的网页设计中,您是否有机会让单个客户端使用同一个 HTTP 会话同时处理多个未完成的请求?这似乎很难做到,除非您将单个 HTTP 会话绑定到多个套接字。(又名,AJAX)如果不这样做,就服务器而言,给定客户端的 HTTP 访问将是单线程的,这意味着单个会话实际上是线程安全的。

Synchronization of your session objects will make the application safer against future changes that make your web application capable of having multiple simultaneous requests, so it's not a bad idea. In modern Java implementations, synchronization does not have the large cost that was previously associated with it, especially when the synchronization is usually uncontended. If your application uses AJAX, which implies that you expect multiple in-flight simultaneous requests to your web server, then synchronization is a must.

会话对象的同步将使应用程序更安全,以防止将来的更改使您的 Web 应用程序能够同时处理多个请求,因此这不是一个坏主意。在现代 Java 实现中,同步没有以前与之相关的巨大成本,尤其是在同步通常是无竞争的情况下。如果您的应用程序使用 AJAX,这意味着您期望对您的 Web 服务器同时进行多个请求,那么同步是必须的。

回答by DefLog

The session is not thread safe and neither the get not the set methods are guaranteed to be thread safe. In general in a servlet container you should assume to be in a multi threaded environment and no provided tooling is safe.

会话不是线程安全的,并且 get 和 set 方法都不保证是线程安全的。通常,在 servlet 容器中,您应该假设处于多线程环境中并且没有提供的工具是安全的。

This also goes for the objects you store in the session. The session itself will not manipulate the stored object but you can retrieve the object in different thread and attempt to manipulate it. It is up to you to examine your own code to see if race conditions are possible.

这也适用于您存储在会话中的对象。会话本身不会操作存储的对象,但您可以在不同的线程中检索对象并尝试操作它。由您来检查自己的代码以查看竞争条件是否可能。

The code example you posted is valid, but the problem may exist beyond the limited scope of your example. It assures there are no conditions while setting to the session, but there is nothing preventing an other thread to override the set. If the code in your request depends of the value remaining unchanged you could still be in trouble.

您发布的代码示例是有效的,但问题可能存在于您示例的有限范围之外。它确保在设置会话时没有任何条件,但没有什么可以阻止其他线程覆盖设置。如果您请求中的代码取决于保持不变的值,您仍然可能遇到麻烦。

回答by McDowell

Servlet 2.5 spec:

Servlet 2.5 规范:

Multiple servlets executing request threads may have active access to the same session object at the same time. The container must ensure that manipulation of internal data structures representing the session attributes is performed in a threadsafe manner. The Developer has the responsibility for threadsafe access to the attribute objects themselves. This will protect the attribute collection inside the HttpSession object from concurrent access, eliminating the opportunity for an application to cause that collection to become corrupted.

多个执行请求线程的 servlet 可以同时主动访问同一个会话对象。容器必须确保以线程安全的方式对表示会话属性的内部数据结构进行操作。开发人员负责对属性对象本身进行线程安全访问。这将保护 HttpSession 对象内的属性集合免受并发访问,从而消除应用程序导致该集合损坏的机会。

This is safe:

这是安全的:

// guaranteed by the spec to be safe
request.getSession().setAttribute("foo", 1);

This is notsafe:

这是不是安全的:

HttpSession session = request.getSession();
Integer n = (Integer) session.getAttribute("foo");
// not thread safe
// another thread might be have got stale value between get and set
session.setAttribute("foo", (n == null) ? 1 : n + 1);

This is notguaranteed to be safe:

不能保证是安全的:

// no guarantee that same instance will be returned,
// nor that session will lock on "this"
HttpSession session = request.getSession();
synchronized (session) {
  Integer n = (Integer) session.getAttribute("foo");
  session.setAttribute("foo", (n == null) ? 1 : n + 1);
}

I have seen this last approach advocated (including in J2EE books), but it is not guaranteed to work by the Servlet specification. You could use the session ID to create a mutex, but there must be a better approach.

我已经看到提倡的最后一种方法(包括在 J2EE 书籍中),但是 Servlet 规范不保证它可以工作。您可以使用会话 ID 创建互斥锁,但必须有更好的方法。

回答by OscarRyz

They are not, but most of the times, your clients will only access them with a single thread.

它们不是,但大多数情况下,您的客户端只能使用单个线程访问它们。

Different clients will have different threads and each one will have its own Session.

不同的客户端会有不同的线程,每个客户端都有自己的会话。

As Eddie points out, one situation where you may face two thread accessing the same session is two ajax calls are attempting to modify the same session attribute. Otherwise you won't have problems.

正如 Eddie 指出的那样,您可能面临两个线程访问同一个会话的一种情况是两个 ajax 调用试图修改同一个会话属性。否则你不会有问题。