问题描述
我有一个grails应用程序,它将一个同步块依赖于一个服务。当我在Windows上运行它时,同步按预期工作,但是当我在ams linux上运行时,得到一个StaleObjectStateException。
这个问题在下面的例子中被重现。 >
class TestService {
private final Object $ lock = new Object [0];
TesteSync incrementa(){
synchronized($ lock){
TesteSync t = TesteSync.findById(1)
t.contador ++
t.save(flush:true)
Thread.sleep(10000)
return t
}
}
$ b在我的理解中,发生这种异常是因为多个线程正在尝试保存相同的对象。这就是为什么我使用同步块。
Linux java:
- Java版本1.7.0_85
OpenJDK运行时环境(amzn-2.6.1.3.61.amzn1-x86_64 u85-b01)
- OpenJDK 64位服务器虚拟机(构建24.85-b03,混合模式)
Windows java:
- Java版本1.7.0_79
- Java™SE运行时环境(build 1.7.0_79-b15) $ b
- Java HotSpot™64位服务器虚拟机(版本24.79-b02,混合模式)
任何线索?
谢谢
解决方案如果你正在寻找的是悲观锁定(在任何给定的时间只允许一个事务访问数据),那么 StaleObjectStateException 。
那么你可以使用域类 lock()方法:
class TestService {
static transactional = tr ue
TesteSync incrementa(){
TesteSync t = TesteSync.lock(1)
t.contador ++
return t.save()
}
}
您可以了解关于Grails悲观锁定的更多信息。
PS:Grails服务默认是事务性的。但在我的例子中,我明确地提出了服务事务调用以引起您的注意:该锁由Grails自动发布。我也删除了flush,因为事务提交时数据被刷新。如果您是通过未明确设置为 @Transactional 的控制器方法执行此操作,则需要刷新。
提示:当您通过ID查询,你可以做到这一点......
SomeDomainClass.get(1)
...而不是...
SomeDomainClass.findById(1)
其他资源。
I have a grails application that relies on a synchronized block into a service. When I run it on windows the synchronization works as expected but when I run on ams linux a get a StaleObjectStateException.
The problem is reproduced in the following example.
class TestService { private final Object $lock = new Object[0]; TesteSync incrementa() { synchronized ($lock) { TesteSync t = TesteSync.findById(1) t.contador++ t.save(flush: true) Thread.sleep(10000) return t } }
}
In my understand, this exception occurs because multiple threads are trying to save the same object. That's why I'm using a synchronized block.
Linux java:
- java version "1.7.0_85"
- OpenJDK Runtime Environment (amzn-2.6.1.3.61.amzn1-x86_64 u85-b01)
- OpenJDK 64-Bit Server VM (build 24.85-b03, mixed mode)
Windows java:
- java version "1.7.0_79"
- Java(TM) SE Runtime Environment (build 1.7.0_79-b15)
- Java HotSpot(TM) 64-Bit Server VM (build 24.79-b02, mixed mode)
Any clues?
Thanks
解决方案You are right about why you're getting the StaleObjectStateException.
If what you're looking for is pessimistic locking (allowing only one transaction access to the data at any given time), then you can use the domain class lock() method:
class TestService { static transactional = true TesteSync incrementa() { TesteSync t = TesteSync.lock(1) t.contador++ return t.save() } }
You can learn more about Grails pessimistic locking here.
PS: Grails services are transactional by default. But in my example I explicitly made the service transactional to call something to your attention: The lock is released by Grails automatically when the transaction commits. I also removed the flush because the data gets flushed when the transaction commits. If you were doing this from a controller method that's not explicitly set to @Transactional, then you would need the flush.
TIP: When you query by ID you can do this...
SomeDomainClass.get(1)
...instead of this...
SomeDomainClass.findById(1)
Espero que ajude.
这篇关于grails上的同步块可以在windows上运行,但在linux中不会运行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!