我有一个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。
答案 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来返回错误,而不是让用户等待锁执行相同的操作。