招标系统的“同步”交易

时间:2012-09-16 19:41:06

标签: spring hibernate grails concurrency synchronized

我尝试使用Grails 2.1实现BidService的以下“天真”实现的投标系统(所以Hibernate和Spring) 但它似乎无法阻止加薪条件,这导致不同并发用户的“重复”出价。

一些信息: - BidService默认为交易, - 项目和投标模型使用“version:false”(悲观锁定)

class BidService{
  BidResult processBid(BidRequest bidRequest, Item item) throws BidException {
        // 1. Validation
        validateBid(bidRequest, item)   // -> throws BidException if bidRequest do not comply with bidding rules (price too low, invalid user, ...) 
       // 2. Proces Bid (we have some complex rules to process the bids too, but at the end we only place the bid
       Bid bid = placeBid(bidRequest, item)

       return bid
  }

   Bid placeBid(BidRequest bidRequest, Item item){
      // 1. Place Bid
      Bid bid = new Bid(bidRequest) // create a bid with the bidRequest values
      bid.save(flush: true, failOnError: true)

      // 2. Update Item price
      item.price = bid.value
      item.save(flush: true, failOnError: true)

      return bid      
   }
}

但正如http://grails.org/doc/latest/guide/services.html 9.2 Scoped Services中所述: 默认情况下,对服务方法的访问不同步,因此不会阻止这些方法的并发执行。实际上,因为服务是单例并且可以同时使用,所以在服务中存储状态时应该非常小心。或者采取简单(更好)的道路,永远不会将状态存储在服务中。

我想在整个processBid()方法上使用“synchronized”,但听起来相当粗鲁,可能会引发活动问题或死锁。 另一方面,以异步方式处理出价,阻止发送有关赢得/失去拍卖的直接用户反馈。

在这种情况下使用的任何建议或最佳做法?

PS:我已经问过grails ML,但这是一个相当广泛的Java并发问题。

1 个答案:

答案 0 :(得分:2)

您的服务是无状态的,因此无需同步它,在状态方面需要同步。

此外,您不需要再使用任何锁定..您不会更改现有状态,只需添加新行。此外,我不是GORM专家,但是version: false应该关闭乐观锁定的名称,这并不意味着激活悲观锁定。

从你的问题我不明白你的问题是什么,但是独特的限制是防止数据库重复的原因。