首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Struts2会话并发问题

Struts2会话并发问题
EN

Stack Overflow用户
提问于 2012-04-25 06:06:26
回答 2查看 2.2K关注 0票数 1

我有一些麻烦。

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

我已经编写了简单的实用程序,它使用executor服务首先发送100000个异步请求到action,然后发送到actions。

在第一个动作中,我这样做:

代码语言:javascript
复制
HitCounter.increment();
ActionContext.getContext().getSession().put("counter", HitCounter.getAtomicCounter());
return Action.SUCCESS;

在第二个动作中,我这样做:

代码语言:javascript
复制
System.out.println("From session: "+ActionContext.getContext().getSession().get("counter"));
System.out.println("Actual:"+ HitCounter.getAtomicCounter());
return Action.SUCCESS;

以及我看到的输出(这真的让我抓狂):

代码语言:javascript
复制
From session: 2 
Actual: 69352

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

有没有一种标准的方法可以用来避免Struts2中的并发问题?

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

P.P.S. HitCounter实现:

代码语言:javascript
复制
public class HitCounter {
    private static AtomicInteger counter = new AtomicInteger(0);

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

另外,我删除了Thread.yield();但它没有帮助。:(

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-04-25 14:45:18

您不会在第二个操作中检索HitCounter。

System.out.println("From session: "+ActionContext.getContext().getSession().get("counter"));

上面这行代码只是打印对象。您是否在代码中遗漏了什么?

票数 0
EN

Stack Overflow用户

发布于 2012-04-25 17:41:48

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

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

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

但是请注意,上面的请求是一个HttpServletRequest,它又派生了一个HttpSession对象,这个对象不仅仅是一个由Struts2返回的映射...这意味着必须包装struts2版本,因此可能不符合规范。因此,我们可以实现ServletRequestAware,它为我们提供了一个HttpServletRequest对象,我们可以从中派生一个HttpSession。但正如前面的问题所指出的那样,这一行并不会对我们有多大帮助,所以实现HttpServletRequest将是浪费时间。所有这些都让我想知道Struts2是如何将它为会话返回的映射与一个没有实现映射的HttpSession进行协调的,它甚至没有一个返回映射的方法……

因此,让我们考虑一下目前可能发生的事情。

代码语言:javascript
复制
line1: hitCounter.increment();
line2: ActionContext.getContext().getSession().put("counter", hitCounter.getAtomicCounter());

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

第2a行:我们得到了hitCounter对象的拷贝类型(作为返回类型)。

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

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

一种方法是将AtomicInteger放入它自己的会话中,这避免了拷贝滑入的问题。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10306717

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档