【问题标题】:Java Servlet Context and Session level variablesJava Servlet 上下文和会话级变量
【发布时间】:2011-07-23 13:01:14
【问题描述】:

当多个线程访问/修改上下文变量但无法在会话级别产生相同的行为时,我已经尝试过这种不一致。例如,在服务方法中调用 session.setAttribute("something") 方法不会导致同一 sessionid 的两个请求(这意味着两个线程)进入时出现竞争条件。是因为 Tomcat 为会话变量提供线程安全还是我有完全错了吗?

【问题讨论】:

  • 我非常怀疑tomcat是否提供任何线程安全。您如何测试以多线程方式访问会话属性?我知道使用随机数并不是测试某些东西的最佳方式,但是当我测试多线程问题时,我总是在调用相关代码之前让我的线程休眠一段时间(通常是几秒钟)。只是一个想法。
  • 不是一个好方法,写了一个发送相同会话ID的小程序。我似乎找不到任何资源说会话变量的线程安全是开发人员的责任,但所有讨论都建议应用程序级变量。

标签: java multithreading servlets


【解决方案1】:

Servlet 规范 3.0 版在第 7.7.1 节中明确声明对会话密钥的访问是线程安全的。 但是,对存储在这些键下的元素的访问不是线程安全的。这种情况下的线程安全必须由应用开发者来保证。

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

示例代码来说明这一点:

HttpSession session;
List items;
session.put("cart", items); // thread1 writes cart reference to session, this is thread-safe
...
items = session.get("cart"); // thread1 reads cart reference from session, this is thread-safe
items.get(0); // access to elements of application collection is *not* thread-safe, you must use explicit synchronization here.

我相信这里的“线程安全方式”的意思是HttpSession 访问方法保证是线程安全的,但是所有访问存储在会话中的元素通过这些元素的方法不保证是线程安全的。

【讨论】:

  • 感谢您的回复 Victor,似乎“容器必须确保以线程安全的方式对表示会话属性的内部数据结构的操作”确实回答了我的问题,但您在开始与它背道而驰。
  • @Victor,非常感谢,如果是这样,那么它解释了为什么我在使用 session.setAttribute("key", "value"); 时没有得到竞争条件;
  • @Victor 我假设设置和获取应用程序级变量的情况并非如此?
  • +1 用于区分属性映射本身和其中的值。 Everone 知道这一点,但在使用“线程安全”地图时没有人意识到这一点:)
【解决方案2】:

在阅读了一下之后(其中包括this bug fix),我确实得到了强烈的印象,即会话是线程安全的,或者应该是。

【讨论】:

    【解决方案3】:

    你知道所有的上下文变量都是线程不安全的,除了本地的,所以如果你试图访问/修改这个上下文变量使用锁,在java中它是synchronized对象,更多信息请阅读Head First Servlets & JSP - 第 5 章。祝你好运!

    【讨论】:

      猜你喜欢
      • 2012-04-10
      • 1970-01-01
      • 2010-09-25
      • 1970-01-01
      • 2014-08-11
      • 1970-01-01
      • 2010-12-21
      • 2013-12-06
      • 2011-08-06
      相关资源
      最近更新 更多