HttpSession 线程安全吗?set/get Attribute 操作是否线程安全?

发布于 2024-07-14 18:56:19 字数 188 浏览 15 评论 0原文

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

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

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

这是一个有效的建议吗?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

你不是我要的菜∠ 2024-07-21 18:56:19

Servlet 2.5 规范:

多个servlet执行请求
线程可以主动访问
同时相同的会话对象。
容器必须确保
操纵内部数据
代表会话的结构
属性是在a中执行的
线程安全的方式。 开发商有
线程安全的责任
访问属性对象
他们自己。 这将保护
里面的属性集合
并发中的 HttpSession 对象
访问,消除机会
对于导致该情况的应用程序
集合将被损坏。

这是安全的:

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

这是安全:

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

这是保证安全的:

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

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

Servlet 2.5 spec:

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.

This is safe:

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

This is not safe:

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 not guaranteed 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.

烟织青萝梦 2024-07-21 18:56:19

不。并且由于您不希望同一客户端(带有会话)执行并发请求,因此您应该像 AbstractController 在 Spring MVC 中执行

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

北凤男飞 2024-07-21 18:56:19

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

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

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

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.

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.

谜兔 2024-07-21 18:56:19

它们不是,但大多数时候,您的客户端只能通过单个线程访问它们。

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

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

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.

锦爱 2024-07-21 18:56:19

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

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

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

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.

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文