grails 上的同步块适用于 windows 但不适用于 linux
synchronized block on grails works on windows but no in linux
我有一个 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,混合模式)
Windows java:
- java 版本“1.7.0_79”
- Java(TM) SE 运行时环境(build 1.7.0_79-b15)
- Java HotSpot(TM) 64 位服务器 VM(内部版本 24.79-b02,混合模式)
有什么线索吗?
谢谢
关于为什么会收到 StaleObjectStateException。
你是对的
如果您正在寻找的是悲观锁定(在任何给定时间只允许一个事务访问数据),那么您可以使用域 class lock()方法:
class TestService {
static transactional = true
TesteSync incrementa() {
TesteSync t = TesteSync.lock(1)
t.contador++
return t.save()
}
}
您可以了解有关 Grails 悲观锁定的更多信息here。
PS:Grails 服务默认是事务性的。但在我的示例中,我明确地使服务具有事务性以引起您的注意:锁定由 Grails 自动释放 when the transaction commits。我还删除了刷新,因为数据在事务提交时被刷新。如果您从未明确设置为 @Transactional 的控制器方法执行此操作,那么您将需要刷新。
提示:当您通过 ID 查询时,您可以这样做...
SomeDomainClass.get(1)
...而不是这个...
SomeDomainClass.findById(1)
我有一个 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,混合模式)
Windows java:
- java 版本“1.7.0_79”
- Java(TM) SE 运行时环境(build 1.7.0_79-b15)
- Java HotSpot(TM) 64 位服务器 VM(内部版本 24.79-b02,混合模式)
有什么线索吗?
谢谢
关于为什么会收到 StaleObjectStateException。
你是对的如果您正在寻找的是悲观锁定(在任何给定时间只允许一个事务访问数据),那么您可以使用域 class lock()方法:
class TestService {
static transactional = true
TesteSync incrementa() {
TesteSync t = TesteSync.lock(1)
t.contador++
return t.save()
}
}
您可以了解有关 Grails 悲观锁定的更多信息here。
PS:Grails 服务默认是事务性的。但在我的示例中,我明确地使服务具有事务性以引起您的注意:锁定由 Grails 自动释放 when the transaction commits。我还删除了刷新,因为数据在事务提交时被刷新。如果您从未明确设置为 @Transactional 的控制器方法执行此操作,那么您将需要刷新。
提示:当您通过 ID 查询时,您可以这样做...
SomeDomainClass.get(1)
...而不是这个...
SomeDomainClass.findById(1)