我有一个 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
}
}
}
据我了解,发生此异常是因为多个线程试图保存同一个对象。这就是我使用同步块的原因。
Linux Java:
- java版本“1.7.0_85”
- OpenJDK 运行时环境 (amzn-2.6.1.3.61.amzn1-x86_64 u85-b01)
- OpenJDK 64 位服务器 VM(内部版本 24.85-b03,混合模式)
视窗java:
- java版本“1.7.0_79”
- Java(TM) SE 运行时环境(版本 1.7.0_79-b15)
- Java HotSpot(TM) 64 位服务器 VM(内部版本 24.79-b02,混合模式)
有什么线索吗?
Thanks
你是对的,为什么你会得到陈旧对象状态异常.
如果您正在寻找的是悲观锁定(在任何给定时间只允许一个事务访问数据),那么您可以使用域类lock() method:
class TestService {
static transactional = true
TesteSync incrementa() {
TesteSync t = TesteSync.lock(1)
t.contador++
return t.save()
}
}
您可以了解有关 Grails 悲观锁定的更多信息here https://grails.github.io/grails-doc/latest/guide/GORM.html#locking.
PS:默认情况下,Grails 服务是事务性的。但在我的示例中,我明确地将服务设为事务性,以引起您的注意:锁由 Grails 自动释放当事务提交时 https://grails.github.io/grails-doc/latest/ref/Domain%20Classes/lock.html。我还删除了刷新,因为事务提交时数据会被刷新。如果您是通过未明确设置为的控制器方法执行此操作@事务性,那么你就需要冲洗。
提示:当您通过 ID 查询时,您可以执行以下操作...
SomeDomainClass.get(1)
...而不是这个...
SomeDomainClass.findById(1)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)