2012-09-16 119 views
-2

我嘗試使用Grails 2.1(所以Hibernate和Spring) 以下「Bidish」實現bidging服務,但它似乎無法防止引發條件和這個結果在來自不同併發用戶的「重複」出價中。投標系統的「同步」交易

一對夫婦的信息: - 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作用域服務聲明: 默認情況下,對服務方法的訪問不同步,因此沒有任何東西阻止這些方法的併發執行。實際上,因爲服務是單例,並且可以同時使用,所以在服務中存儲狀態時應該非常小心。或者走簡單(更好)的道路,不要在服務中存儲狀態。

我想在整個processBid()方法上使用「synchronized」,但這聽起來很粗魯,可能會引發活性問題或死鎖。另一方面,以異步方式處理投標,可阻止直接向用戶反饋關於贏/放拍賣的反饋。

在這種情況下使用任何建議或最佳做法? PS:我已經問過grails ML,但它是一個相當寬泛的Java併發問題。

回答

2

您的服務是無狀態的,所以不需要同步它,當涉及到狀態時需要同步。

此外,您不需要再次使用任何鎖定。您不會更改現有狀態,只需添加新行。此外,我不是GORM專家,但version: false應該關閉它的名字所說的樂觀鎖定,這並不意味着激活了悲觀鎖定。

從你的問題我不明白你的問題是什麼,但獨特的約束是防止數據庫中的重複。

+0

驗證步驟需要一些時間並涉及狀態:項目的當前價格,其他出價,動態出價,... 因此,如果碰巧有兩個同時驗證(向右)爲兩個用戶設置出價,將導致重複出價值。我將尋求獨特的方法,即使它意味着在處理動態投標時改變一些邏輯,似乎也會更好。 你可能是正確的版本:錯誤我會檢查文檔。 – Wavyx

+0

version:false會關閉樂觀鎖定,但要使用悲觀鎖定,您需要明確調用item.lock()http://grails.org/doc/latest/guide/GORM.html#locking 我將再次測試,但它是可能更適合獨特的限制 – Wavyx