struts2 action 线程安全同步问题

问题描述:

action在配置文件里的属性为:scope="prototype"

在高并发请求一个action的时候,怎么解决数据不被重复验证!

谢谢!

在下面访问的时候出现都修改了数据
[code="java"]public String threadTest(){
HttpServletRequest request = ServletActionContext.getRequest();
product = productService.getProduct(11440);
if(product.getStatus()==1){
System.out.println(zhe+"==========jinru==========");
try {
Thread.sleep(10000*10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(zhe+"==========kaishi==========");
if("11".equals(zhe)){
System.out.println(zhe+(new Date()));
System.out.println(product.getStatus());
product.setStatus(3); //原来是1
product.setBuyNum(1100); //原来是800
product.setMaxQuantity(2100); //原来是1000
productService.updateProduct(product);
TradeArea ta = tradeAreaService.getTradeArea(11922);
ta.setTradeName("1111");
tradeAreaService.updateTradeArea(ta);
System.out.println(zhe+(new Date())+"end");
}else{
System.out.println(product.getStatus());
System.out.println(zhe+(new Date()));
product.setStatus(4);//原来是1
product.setBuyNum(1300);//原来是 800
product.setMinQuantity(1123); //原来是123
productService.updateProduct(product);
System.out.println(zhe+(new Date())+"end");
TradeArea ta = tradeAreaService.getTradeArea(11923);
ta.setTradeName("11113333");
tradeAreaService.updateTradeArea(ta);
}

    }
     message=zhe;
     request.setAttribute("tipMessage", "../index.jsp"); 
     return "message";
}[/code]

同时几个页面访问这个action的时候,数据都修改了,请问要怎么设置!

这个问题以前也看到过...prototype怎么变成singleton了

struts2 不是没有线程安全的考虑吗?
每个请求都new了个新对象, 典型的牺牲点性能根源上解决问题的做法啊...
跟你代码好像没什么关系.

你是不是用Spring管了,不要用单例

Struts2 的Action对象为每一个请求产生一个实例,因此虽然在Action中定义了很多全局变量,也不存在线程安全问题。
Struts2框架在处理每一个用户请求的时候,都建立一个单独的线程进行处理,值栈ValueStack也是伴随着局部线程而存在 的,在该线程存在的过程中,可以随意访问值栈,这就保证了值栈的安全性。

你现在的这种测试方式,应该是对同一条数据进行更新的操作,因为数据库自身的锁机制,同一条记录不可能同时被修改的。跟struts2的线程安全没有关系。

还有你已经设置为scope="prototype",本身就是支持多线程了,不存在线程同步的问题

首先 你的the用的就不能说明问题
你用静态变量做判断
应该是让你一次请求sleep, 然后第二次请求去修改数据 对吧
static {
the = true;
}
...
if (the) {//是不是线程安全就看第二个对象会不会在此等待,和修改数据没关系
the = false;
sleep....
}
这样当然会被第二次修改掉了.
第二个请求是个新对象, 获得新的连接 修改数据库数据
这个没什么问题啊

这是两个对象,你sleep那个对象不会再第二个对象进来的时候还会去等待对象一sleep完
所以说每个对象都是新的. 第二个请求一旦进来就不会走if直接去修改了对象.

struts2不建议我们做一些操作,你可以留意下. 当然也是针对想这样的问题

做判读为什么要传进去?
设计什么?

static{
//利用这个可以在类第一次初始化时做一些操作,仅仅执行一次
}

静态变量也是个好办法

[quote]我是想让2个方法都执行 [/quote]

不判断不就都执行了?? 能否说的清楚些?

我之前也遇到过这种关于action的并发问题!
我想,如果你使用的是集群服务器或者是多例的,那跟线程应该是没有关系的。
我这边最后的解决办法是在数据库中加“锁”,这个锁不是数据库中的乐观锁那种操作,而是给你要操作的数据行加以限制,举例来说吧:

现在表中有一条记录:
ID STATUS NAME
1 1 NAME1

如果说有一个操作是修改STATUS为1的记录的NAME值为NAME2,那么SQL语句一般我们会这样写:
UPDATE TABLE SET NAME='NAME2' WHERE STATUS=1;

现在给这条SQL语句再加一个限制:
UPDATE TABLE SET NAME='NAME2' WHERE STATUS=1 AND NAME='NAME1';

这样就给记录加了一个锁,假如说现在有并发情况,用户A和用户B同时点击操作,总会有一个先操作,而一个后操作,那么先操作的会修改成功,而后操作的用户,因为NAME已经被第一个用户修改成NAME2,那UPDATE语句就执行失败了,这样就不会出现并发现象了。

当然,这种操作需要在程序UPDATE前,先将要修改的字段值查询出来,然后作为限制条件加到SQL语句中。

希望可以帮到你,我因为这个问题困扰了很久!

单例就会这样...

这属于数据的查询并更新问题,要保证这一系列的操作在一个事务中完成。这个工作无法在web容器层面来完成,需要在数据库层面上进行。
以mysql为例:
首先为当前数据库操作添加事务,
然后执行 select ... for update 语句查询你所需的数据,数据库会对查询到的结果进行加锁。
再然后就可以放心地执行你的更新逻辑了。在此期间其他对被锁的记录的select ... for update以及更新,删除的请求都会阻塞,直到当前线程操作完成,提交事务或回滚以后才得以继续执行。从而保证数据的完整。