我有一些麻烦。
例如,我有两个动作:第一个和第二个。
我已经编写了简单的实用程序,它使用executor服务首先发送100000个异步请求到action,然后发送到actions。
在第一个动作中,我这样做:
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中的并发问题?
P.S. 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();
}
}另外,我删除了Thread.yield();但它没有帮助。:(
发布于 2012-04-25 14:45:18
您不会在第二个操作中检索HitCounter。
System.out.println("From session: "+ActionContext.getContext().getSession().get("counter"));
上面这行代码只是打印对象。您是否在代码中遗漏了什么?
发布于 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进行协调的,它甚至没有一个返回映射的方法……
因此,让我们考虑一下目前可能发生的事情。
line1: hitCounter.increment();
line2: ActionContext.getContext().getSession().put("counter", hitCounter.getAtomicCounter());第1行:我们增加一些全局hitCounter对象。
第2a行:我们得到了hitCounter对象的拷贝类型(作为返回类型)。
第2b行:我们在会话中设置hitCounter值。
由于HitCounter的线程安全特性,我们知道第1行总是很好的……但是line2呢?我们可以看到有两个部分,如果线程在获取hitCournter副本和设置hitCounter之间挂起,就会出现竞争情况……从这一点执行的最后一个线程将获胜。
一种方法是将AtomicInteger放入它自己的会话中,这避免了拷贝滑入的问题。
https://stackoverflow.com/questions/10306717
复制相似问题