-2

我尝试使用 Grails 2.1(所以 Hibernate 和 Spring)使用以下 BidService 的“幼稚”实现来实现出价系统,但它似乎无法防止提高条件,这导致来自不同并发用户的“重复”出价。

一些信息: - BidService 默认是事务性的, - 项目和投标模型使用“版本:假”(悲观锁定)

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() 方法上使用“同步”,但这听起来很粗鲁,可能会引发活跃度问题或死锁。另一方面,以异步方式处理出价会阻止直接向用户发送有关赢得/输掉拍卖的反馈。

在这种情况下使用任何建议或最佳实践?

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

4

1 回答 1

2

你的服务是无状态的,所以不需要同步它,当涉及到状态时需要同步。

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

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

于 2012-09-16T20:13:50.700 回答