在Spring Boot中,是否可以使用两种不同的方法“锁定”和“解除锁定”悲观锁?

3

我目前在自动售货机项目中需要使用悲观锁。当有多人选择商品时,我希望使用悲观锁防止两个人同时选择同一件商品。我的项目是Java、Spring Boot。

我能否通过一个方法调用来执行"悲观锁"的加锁过程,并在另一个方法调用中以某种方式解除"悲观锁"?("加锁"过程在用户确认商品时执行,"解锁"过程在用户支付商品或希望重新选择商品时执行)还是有更好的解决方案?


请告诉我们您正在使用哪个类来实现锁定。 - Stephen C
2
我必须说,整件事情都有点“过度思考”。现实生活中的普通自动售货机一次只能为一个人提供服务。如果有多个人,他们就排队等候... - Stephen C
在这种情况下,所有产品都是通过在线界面选择的,因此支持多用户使用。谢谢@StephenC - Power_tile
所以它不是自动贩卖机。这是一个标准的购物网站。 - Stephen C
是的,这是一个连接到实体售货机的标准网站。很抱歉语句不清楚。 - Power_tile
1个回答

2
Lock API允许一个方法获取锁并允许另一个方法释放锁。
特定的Lock实现可能允许一个线程获取锁,而另一个线程释放锁。但是ReentrantLock不行。每个Lock实现的javadoc都应该记录此方面的信息。
然而,我认为您根本不应该使用Java语言锁进行建模,无论是原始对象锁还是Lock。它们旨在为某些代码块提供互斥,从而控制对共享数据结构的访问和更新。
我认为您应该将其建模为以下所使用的“持有”或“保留”:
  • 用户选择产品时会获取持有
  • 当:
    • 用户购买产品
    • 用户取消交易
    • 用户花费太长时间来完成交易
    • 用户......离开
    时,将释放持有。
因此,持有可能包括:
  • 持有ID
  • 产品标识符
  • 产品数量
  • 用户ID或会话ID
  • 到期时间戳
如果“持有”存储在您的数据库中,则最容易实现。
您只需要维护这样一个不变式:产品的持有数小于或等于该产品未售出的数量。
最后,您需要一些东西来自动释放已达到其到期时间的“持有”。还需要处理用户在其“持有”到期后尝试购买物品的情况。

对于LockAPI,您是指Java语言中的@Lock注释还是标准Lock - Power_tile
java.util.concurrent.locks.Lock 但我认为 @Lock 也不对。它还在代码区域上提供了互斥。 - Stephen C
我在尝试锁定/解锁SQL数据库中的行,而不是锁定程序内的变量。似乎java.util.concurrent.locks更适用于锁定线程,而不是锁定数据库。 - Power_tile
似乎我尝试的操作(在SQL表中锁定和释放行)被阻止以保护数据库。将锁存储在单独的表中的方法是我最终使用的方法。谢谢@Stephen C。 - Power_tile

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接