小编典典

Grails上的同步块可在Windows上使用,但在Linux中无法使用

java

我有一个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运行时环境(内部版本1.7.0_79-b15)
  • Java HotSpot(TM)64位服务器VM(内部版本24.79-b02,混合模式)

有什么线索吗?

谢谢


阅读 225

收藏
2020-11-23

共1个答案

小编典典

您为什么要获取 StaleObjectStateException 是正确的。

如果您要查找的是悲观锁定(在任何给定时间只允许一个事务访问数据),则可以使用域类 lock() 方法:

class TestService {
    static transactional = true

    TesteSync incrementa() {
        TesteSync t = TesteSync.lock(1)
        t.contador++
        return t.save()
    }
}

您可以在此处了解更多有关Grails悲观锁定的信息

PS:默认情况下,Grails服务是事务性的。但是在我的示例中,我显式地使服务成为事务性的,以引起您的注意:Grails
在事务提交时自动释放锁定。我还删除了刷新,因为在事务提交时数据将被刷新。如果您是通过未显式设置为
@Transactional 的控制器方法执行此操作的,则需要进行刷新。

提示:通过ID查询时,您可以执行此操作…

SomeDomainClass.get(1)

而不是这个

SomeDomainClass.findById(1)
2020-11-23