在多用户环境中使grails服务方法成为原子

时间:2012-12-26 23:06:21

标签: java grails parallel-processing atomic

我有一个grails服务方法,load,我一次只希望一个用户能够运行。我曾尝试使用Grails悲观锁,但它有时只能工作。在我的控制器中,我有:

try {
    def country = Country.lock(id)
    myService.load(country)
} catch (CannotAcquireLockException ex) {
    flash.message = "Another user is modifying ${Country.get(id)}"
}

使myService的load方法成为原子的最佳方法是什么?

如果我想要两个方法是原子的(当一个方法执行时,两个方法都不能执行)怎么办?

我的服务方法:

def load(id) {
    def country = Country.get(id)
    country.states.each {
        ...
        it.save(flush: true)
    }
}

将synchronized关键字添加到此方法会导致保存时出现StaleObjectStateException。

3 个答案:

答案 0 :(得分:2)

Grails服务默认为单身,负责部分问题。您还应该使服务方法同步以实现您想要的目标:

def synchronized load(country) { ... }

答案 1 :(得分:2)

您可以将@synchronized注释与自定义同步锁一起使用。这样您就不会同步this(整个服务类),只会同步给定的方法。

代码示例

class MyCustomService

private final myLock = new Object()

@Synchronized("myLock")
def myRunOneAtATimeMethod(int x, int y)
    return x+y 

有关同步的更多信息:http://groovy.codehaus.org/gapi/groovy/transform/Synchronized.html

答案 2 :(得分:1)

这可以使用ReentrantLock作为普通的Java同步问题来解决。我可以使用isLocked来返回错误,而不是让用户等待锁执行相同的操作。