【问题标题】:java synchronized method fails in servletjava同步方法在servlet中失败
【发布时间】:2014-05-13 22:35:05
【问题描述】:

我有一个与 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()

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

因为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(); 
}

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

【问题讨论】:

  • (您可以更改您的个人资料以添加您的姓名。不要在问题中添加感谢和签名,这是噪音。)
  • @user3634440 编辑您的帖子,而不是将代码放入 cmets。
  • 注明。刚刚解决了这个问题,并将删除有问题的评论。帖子已更新。
  • 你能告诉我们returnAllObjects方法吗?
  • 大卫华莱士:是的,刚刚更新。

标签: java hibernate servlets synchronization


【解决方案1】:

cmets中的匿名者给出了正确答案:问题一定是hibernate数据库中的Hotel对象,而不是同步方式。尽管计数器方法已正确同步,但如果在此算法之外修改酒店对象,则这些访问将不会同步。

因此,正确的答案是仔细检查对酒店对象的所有数据库访问,并确保在此循环进行时该对象没有在其他地方被修改,或者将酒店对象中的计数器重构到专用存储中。

【讨论】:

    猜你喜欢
    • 2016-04-05
    • 1970-01-01
    • 2014-05-23
    • 2016-10-05
    • 1970-01-01
    • 2019-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多