java同步方法在servlet中失败

时间:2014-05-13 22:35:06

标签: java hibernate servlets synchronization

我有一个与hibernate交互的java servlet。因此有必要在系统上生成一个检查ID:

for (long j = 0; j < soldProductQuantity.longValue(); j++) {
    checkId = Hotel.getNextMcsCheckAndIncrement();                  
    checkIdString = checkId.toString();
    McsCheck.generateCheck(checkIdString);                                  
}

其中getNextMcsCheckAndIncrement()定义为

 static public synchronized Long getNextMcsCheckAndIncrement()

它使用hibernate从数据库中提取一个值,对它执行一些操作,将修改后的值存储回来,然后返回该数字。

由于getNextMcsCheckAndIncrement是同步的,我希望没有两个检查具有相同的数字,因为没有两个线程可以同时输入该方法。

然而,我可以在我的数据中看到多个检查ID的重复实例。很明显,这不起作用。我错过了什么?

按要求执行getNext:

// Increment FIRST, then return the resulting value as the current MCS check value.
static public synchronized Long getNextMcsCheckAndIncrement() {
    Hotel theHotel = null; 
    Long checkCounter; 
    @SuppressWarnings("unchecked")                  
    List<Hotel> hotelList = Hotel.returnAllObjects(); 
    for (Hotel currentHotel : hotelList) {  // there should be only one. 
                theHotel = currentHotel;
        }

    checkCounter = theHotel.getMcsCheckCounter()+1; 
    theHotel.setMcsCheckCounter(checkCounter);
    theHotel.update(); 
    return checkCounter; 

} 

static public List returnAllObjects() {
    return Hotel.query ("from Hotel"); 
}   

static public List query(String queryString) {
    Session session = HibernateUtil.getSessionFactory().openSession();
    List result = session.createQuery(queryString).list();  
    session.close(); 
    return result;
}

public void update() {
    Session session = HibernateUtil.getSessionFactory().openSession();
    Transaction transaction = session.beginTransaction();
    session.update(this);
    transaction.commit();
    session.close(); 
}

是的,我知道这不是最好的方法,我会及时解决这个问题。但直接的问题是并发失败的原因。

1 个答案:

答案 0 :(得分:0)

评论中的匿名给出了正确的答案:问题必须是hibernate数据库中的Hotel对象,而不是同步方法。虽然计数器方法已正确同步,但如果在此算法之外修改了酒店对象,则不会同步这些访问。

因此,正确的答案是仔细检查对酒店对象的所有数据库访问,并确保在此循环正在进行时不在其他位置修改对象,或者将计数器从Hotel对象重构为专用存储。