grails上的Synchronized块在Windows上工作,但在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 Runtime Environment (amzn-2.6.1.3.61.)amzn1-x86_64 u85-b01)
  • OpenJDK 64位Server VM (build 24.85-b03, mixed mode)
Windows java:

  • java版本"1.7.0_79"
  • Java(TM) SE Runtime Environment (build 1.7.0_79-b15)
  • Java HotSpot(TM) 64位Server VM (build 24.79-b02, mixed mode)

什么线索吗?

谢谢

你是对的,为什么你得到StaleObjectStateException

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

class TestService {
    static transactional = true
    TesteSync incrementa() {
        TesteSync t = TesteSync.lock(1)
        t.contador++
        return t.save()
    }
}

你可以在这里了解更多关于Grails悲观锁的信息。

PS: Grails服务默认是事务性的。但是在我的示例中,我显式地将服务设置为事务性,以引起您的注意:当事务提交时,锁将由Grails自动释放。我还删除了刷新,因为在事务提交时数据会刷新。如果你从一个没有显式设置为@Transactional的控制器方法中执行此操作,那么你将需要flush。

提示:当你按ID查询时,你可以这样做…

SomeDomainClass.get(1)

…而不是这个…

SomeDomainClass.findById(1)

相关内容

最新更新