【问题标题】:Pessimistic Locking strange behaviour悲观锁定奇怪的行为
【发布时间】:2023-03-29 14:26:01
【问题描述】:

我正在开发一个模块,我使用悲观锁定来锁定一行。

我在服务方法中使用了下面的代码:

examSession = ExamSession.lock(ID)
println "after lock " + new Date()
......
...........
examSession.addTo.........(object)
....................................
examSession.save()........
.......................................
trigger payment.......
...........................

当我在 2 个浏览器中(几乎同时)点击一个按钮以到达服务方法代码时,我观察到另一个线程(第二个浏览器)在 lock 语句后暂停,甚至不执行它后面的 print 语句。它在等待第一个线程完成/提交事务 3-4 秒后执行。但是我已经读过,在悲观锁定的情况下,只有数据库读取操作被暂停。它应该至少执行了 print 语句。它是怎么发生的?

Grails 文档也没有详细说明 lock()。请澄清。

【问题讨论】:

  • ExamSession.lock(ID) 是什么?
  • ExamSession 是一个领域类(相当于hibernate实体类)。 lock() 在具有指定 ID 的行上获取锁。

标签: java multithreading hibernate grails grails-orm


【解决方案1】:

ExamSession.lock(ID) 获取(或尝试获取)锁。显然如果已经获取了,就不会继续执行了。

这正是悲观锁定应该做的事情,它完全按照它应该的方式工作。它不会在 lock 语句之后暂停。它暂停lock(),因为它无法获得排他锁。

【讨论】:

  • 啊,,,你是对的。 +1 感谢您的回复。我为并发座位预订实现了它,其中检查了座位可用性,将座位分配给用户(先到先得)并触发付款。假设只剩下 1 个席位,那么只有 1 个用户可以认领该席位。你认为这是正确的方法吗?
  • 悲观锁定肯定会阻止多个用户尝试使用特定对象。但是,您很可能需要在lock() 之后检查对象是否仍然空闲,否则等待锁定的另一个用户将“超额预订”第一个用户所做的内容。你不想这样。
  • @Kayaman @VivekSadh 您基本上希望阅读ExamSession 并在读取时应用锁定以避免Kayaman 描述的上述问题。在 JPA 中,这相当于使用 entityManager.find(ExamSession.class, theId, LockModeType.PESSIMISTIC_WRITE);。这告诉数据库您将要更新该行,您要锁定它、读取它并将该行返回给应用程序。在您提交或回滚事务之前,没有人可以做任何事情,甚至不能阅读它。
  • @Naros 感谢您的信息。卡亚曼。是的,在 lock 语句之后,我确实应用了验证并检查了 seatRemaining 是否 > 0 然后只有 book else 返回并显示消息。
猜你喜欢
  • 1970-01-01
  • 2010-09-12
  • 1970-01-01
  • 2014-08-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多