这个问题不知道应该叫多线程问题还是并发了情况:
下面的方法是用来生产 原料单号 的。(具体就是每次接收到ADD请求就去数据库获取最后一个记录,做+1操作,存入数据库,作为当前原料单的号码)问题:
当多个request请求来时,+1还没有做完,另一个请求就获取了原来的值,导致多个请求都是同样的 原料单号。。
我尝试锁定这个方法,本地用main 测试,有效。但是web 测试 无效。请大牛帮忙!! public synchronized String TPOID(String ProxyId) { GenIDBean newGB = new GenIDBean();
GenIDDao gd = new GenIDDao();
Date d = new Date();
SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd");
Map<String, Object> mapO = new HashMap<String, Object>();
mapO.put("label0", 1);// 1=原料单号生成
mapO.put("prefix0", ProxyId);
mapO.put("datestr0", sd.format(d));
try {
List<GenIDBean> lst = gd.getIDL(1, mapO);
if (lst != null && lst.size() > 0) {
int isuffix = Integer.parseInt(lst.get(0).getSuffix()) + 1;
newGB.setSuffix(isuffix + "");
newGB.setPrefix(lst.get(0).getPrefix());
newGB.setDatestr(lst.get(0).getDatestr());
} else {
newGB.setSuffix(1 + "");
newGB.setPrefix(ProxyId);
newGB.setDatestr(sd.format(d));
} newGB.setLabel(1);
if (gd.addgb(newGB) > 0) {
return (newGB.getPrefix() + newGB.getDatestr() + newGB.getSuffix()).replaceAll("-", "");
}
} catch (BaseDAOException e) {
e.printStackTrace();
return "";
} catch (BaseDaoSupportException e) {
e.printStackTrace();
return "";
}
return "";
}

解决方案 »

  1.   

    你是对数据库操作,这样每次取是耗资源的,还不如利用数据库的sequence等机制自动生成+1的结果,这样也不需要select一遍再update了
      

  2.   

    从web方面来看,servlet可以用单线程模式工作,也就是实现SingleThreadModel接口,不过这个方法在servlet2.4标准中已经被提示为不安全,不过好处在于实现简单,目前来说这个接口貌似还是可以达到单线程实例的目的
    从数据库方面来看,你这个写法就有点问题了,应该让数据库自己进行增加的动作,而不是select出来再update
    可以考虑的办法是update中使用sql子句,或者写成一个存储过程,用存储过程加锁
      

  3.   

    楼主说的很明白了,main函数测试有效,web测试无效。既然main函数测试有效,那么说明同步代码正常。不需修改同步代码。
    我推测是这个原因:此方法所在的类的对象,每次请求都会被创建一个,导致加锁无效,可以考虑将此类做成单例,如果不能做成单例,那么就不要使用同步方法,另外找一个application中唯一的对象,对其加锁。也就是说,此方法每次执行都必须获取application中唯一的对象的锁。
      

  4.   

    我已经尝试过使用单例。。依然是java 程序调用有效。。再web环境下的多请求,无效
      

  5.   

    不是单例 是servlet的单线程模式
    未指定单线程情况下,servlet请求池预先在池中分配数个servlet实例,对于每个请求,会由池中的实例对象负责处理请求
      

  6.   

    楼主。你这个方法并非静态的,这样synchronized 是锁住当前实例的,也就是你在不同对象里面调用这个方法的话他们是完全没有同步的,你把这个方法变成static的保证没有问题
      

  7.   

    如果数据库支持sequence, 直接用sequence
    如果数据库如mysql 不支持,试试 static Object LOCK;function(){
        synchronized (LOCK) {
            //do sth...
        }
    }如果还不行,试试 java自带的concurrent包
    如:
    java.util.concurrent.locks.Lock
    }
      

  8.   

    不晓得楼主你看懂了没有?
    你的main是怎么写的,贴出来看看