gpt4 book ai didi

java - Struts2 session 并发问题

转载 作者:太空宇宙 更新时间:2023-11-04 08:16:31 27 4
gpt4 key购买 nike

我遇到了一些麻烦。

例如,我有两个操作:第一和第二。

我编写了简单的实用程序,它使用执行程序服务向 action First 和 actions Second 发送 100000 个异步请求。

在第一个行动中,我做的是:

HitCounter.increment();
ActionContext.getContext().getSession().put("counter", HitCounter.getAtomicCounter());
return Action.SUCCESS;

在第二个行动中,我做:

System.out.println("From session: "+ActionContext.getContext().getSession().get("counter"));
System.out.println("Actual:"+ HitCounter.getAtomicCounter());
return Action.SUCCESS;

我看到的输出(这真的让我生气):

From session: 2 
Actual: 69352

一段时间后,当我仅从浏览器使用此 Fitst 操作/第二个操作并且没有并发请求到来(由我的加载实用程序生成)时,结果“稳定”为实际值。因此,我遇到了并发问题。

我应该使用一种标准方法来避免 Struts2 中的并发问题吗?

附注HitCounter 是线程安全的,因为它只包含一个字段,而且是 AtomicInteger。

P.P.S。 HitCounter实现:

public class HitCounter {
private static AtomicInteger counter = new AtomicInteger(0);

public static void increment() {
counter.incrementAndGet();
}
public static int getAtomicCounter() {
return counter.get();
}
}

P.P.P.S。我删除了 Thread.yield();但这没有帮助。 :(

最佳答案

Struts2 操作是线程安全的,因为它们使用线程本地存储...即存在从变量到值的每线程映射。因此不存在共享的可变的状态并且不需要同步。

但是,诸如 session 之类的资源不能以这种方式处理,因此必须小心并发访问。这个问题讨论了这些问题:Using request.getSession() as a locking object?

根据这个问题: Is HttpSession thread safe, are set/get Attribute thread safe operations? Servlet 规范声明以下内容是线程安全的: request.getSession().setAttribute("foo", 1);

但是请注意,上面的请求是一个 HttpServletRequest,它又派生出一个 HttpSession 对象,该对象不仅仅是 Struts2 返回的映射...这意味着必须包装 struts2 版本,因此可能不遵守规范。因此,我们可以实现 ServletRequestAware,它为我们提供一个 HttpServletRequest 对象,我们可以从中派生 HttpSession。但是这一行不会像前面的问题指出的那样对我们有太大帮助,因此实现 HttpServletRequest 将是浪费时间。查找所有这些内容让我想知道 Struts2 如何协调它为 Session 返回的 Map 与 HttpSession 的关系,而 HttpSession 没有实现 Map,甚至没有返回 Map 的方法...

所以让我们考虑一下当前可能发生的情况......

line1: hitCounter.increment();
line2: ActionContext.getContext().getSession().put("counter", hitCounter.getAtomicCounter());

第 1 行:我们增加一些全局 hitCounter 对象。

第 2a 行:我们获得 hitCounter 对象的副本(int 作为返回类型)。

第 2b 行:我们在 session 中设置 hitCounter 值。

由于 HitCounter 的线程安全特性,我们知道第 1 行总是好的...但是第 2 行呢?我们可以看到有两个部分,如果一个线程在获取 hitCournter 副本和设置 hitCounter 之间挂起,就会出现竞争条件...从此时开始执行的最后一个线程将获胜。

一种方法是将 AtomicInteger 本身放入 session 中,这可以避免副本滑入的问题。

关于java - Struts2 session 并发问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10306717/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com