读书人

多线程上谨慎对待基类(抽象类)中的成

发布时间: 2012-11-03 10:57:42 作者: rapoo

多线程下谨慎对待基类(抽象类)中的成员变量
有这么个需求:
做开发一套在oracle和mysql中做业务数据复制,其中具体的业务还没确定,目前需要开发一套
框架,需要在业务确定后,只需做少了开发即可实现,我使用了ibatis+spring
,以后扩展时,只需增加ibatis的配置文件即可,而配置文件中的每个ID都是由以下规则生成:
业务识别码+新增/删除等统一的后缀。
如下结构:

1、DAO部分

public abstract class Base{   private String name;   private String code;   public String getName(){return name;}   public String getCode(){return code;}   public void setName(String name){this.name=name;}   public void setCode(String code){this.code = code;}   public String getInsertSqlName()   {       return this.code+"insert";   }   public abstract insert(...);   public abstract query(...);}public class ADao extends Base{       public map insert(...)   {      String sqlName = this.getInsertSqlName();      //用ibatis操作数据库   }   public map query(...)   {      xxxxx   }}public class  BDao extends Base{       public map insert(...)   {      String sqlName = this.getInsertSqlName();      //用ibatis操作数据库   }   public map query(...)   {      xxxxx   }}public class CDao extends Base{       public map insert(...)   {      String sqlName = this.getInsertSqlName();      //用ibatis操作数据库   }   public map query(...)   {      xxxxx   }}

2、Service部分
根据数据库配置动态创—AO,大概如下:
   String name=从数据库读取    String code = 从数据库读取    Base dao = ServFactory.getDao(name,code);   dao.insert(xxx);   dao.query(xxx);


3、为了重用DAO,如上面Service部分,使用ServFactory创—AO,
原理就是将创建的DAO放到map中,在getDao前先检查map中有没有DAO,没有则创建。

单线程运行下没问题。

但是在并发处理时,发现查询出来的数据错位了,明明查A的数据,结果返回了B的数据。

使用debug跟踪发现,DAO中的name和code会在执行insert后的query被突然改变,原来在并发下有其他请求的code被其他获取相同DAO的线程改变,导致最后执行的SQL不是预期的SQL。

解决方法有2:
1、不缓存DAO,每次创建个新DAO

2、不适用Base的成员变量,直接将name和code通过参数传入到insert和query中

我选择了后者。

读书人网 >编程

热点推荐