grails 上的同步块在 Windows 上有效,但在 Linux 上无效

2024-05-10

我有一个 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(使用前将#替换为@)

grails 上的同步块在 Windows 上有效,但在 Linux 上无效 的相关文章

随机推荐