3

I am currently having the need of using pessimistic lock in my vending machine project. When more than 1 person is choosing their products, I would like to use the pessimistic lock to prevent both people from selecting the same product. My project is Java, Spring Boot.

Is it possible for me to execute the "lock" of the pessimistic lock in one method call and somehow "unlock" the pessimistic lock in another method call? (The "lock" process is executed when the user confirms the product, and the "unlock" process is executed when the user either pays for the products or desire to re-choose the products.) Or are there any better solutions to this problem?

Vy Do
  • 46,709
  • 59
  • 215
  • 313
Power_tile
  • 578
  • 1
  • 6
  • 18
  • Please tell us what class you are using to implement the lock. – Stephen C Jun 13 '20 at 02:30
  • 2
    I must say though that this whole thing smells of "over thinking". A normal real-life vending machine only caters for one person using the machine at a time. If there are multiple people, they form a line ... – Stephen C Jun 13 '20 at 02:33
  • In this case all products are selected by an online interface, so multiuser uses are supported. Thanks @StephenC – Power_tile Jun 13 '20 at 04:50
  • So it is not a vending machine. It is a standard website where you buy things. – Stephen C Jun 13 '20 at 05:02
  • Yes it is a standard website connected to a physical vending machine. sorry for the unclear statement – Power_tile Jun 13 '20 at 10:39

1 Answers1

2

The Lock API allows one method to acquire a lock and another method to release it.

A particular implementation of Lock could allow one thread to acquire a lock and another on release it. But ReentrantLock doesn't. The javadocs for each Lock implementation should document this aspect.


However, I think you should not be modelling this using Java language locks at all; either primitive object locks or Lock. These are designed to provide mutual exclusion for certain blocks of code, and thereby to control access and update to a shared data structure.

I think you should be modelling this as "holds" or "reservations" used as follows:

  • The user acquires hold when they select the product
  • A hold is released when:
    • the user buys the product
    • the user cancels the transaction
    • the user takes too long to complete the transaction
    • the user ... walks away

So a hold might consist of:

  • a hold id
  • a product identifier
  • a product quantity
  • a user id or a session id
  • an expiry timestamp

It will be easiest to implement if the "holds" are stored in your database.

You just need to maintain the invariant that the number of holds for a product is less or equal to the number of unsold items of that product.

Finally, you will need something to automatically release holds that have reached their expiry. And something to deal with the case where a user attempts to purchase an item after their hold has expired.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • For the ```Lock``` api, are you referring to the ```@Lock``` annotation or the standard ```Lock``` in java language? – Power_tile Jun 13 '20 at 10:40
  • `java.util.concurrent.locks.Lock` But I don't think `@Lock` would be right either. It is also providing mutual exclusion on code regions. – Stephen C Jun 13 '20 at 10:51
  • Here I am trying to lock/unlock rows in the sql database instead of locking a variable inside my program. Seems like ```java.util.concurrent.locks``` is more for locking threads instead of locking the database – Power_tile Jun 13 '20 at 11:46
  • Seems that what I tried to do (locking and releasing rows in SQL table) is prevented in order to protect the database. The method of storing locks in a separate table is the method I finally used. Thanks@Stephen C – Power_tile Jun 13 '20 at 12:52