- We use ReentrantLock for locking the Resource(totalSeats)
- Incase anything goes wrong (Exception being thrown etc.) you want to make sure the lock is released no matter what.
- Calling the reserveSeats method should be done inside separate threads
ReservationSystem.java
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class ReservationSystem { private Integer totalSeats; private final Lock lock = new ReentrantLock(); public ReservationSystem(Integer totalSeats){ this.totalSeats = totalSeats; } public Integer getTotalSeats(){ return totalSeats; } public void reserveSeats(String userName, int numOfSeats){ lock.lock(); try{ if(numOfSeats >0 && totalSeats>numOfSeats){ totalSeats -= numOfSeats; System.out.println(userName + " has reserved "+ numOfSeats + " with " + totalSeats + " still available"); }else{ System.out.println("Seats not Available"); } }finally { lock.unlock(); } } }
BookSeat.java
public class BookSeat { public static void main(String[] args) { ReservationSystem objResSys = new ReservationSystem(100); System.out.println("Total available Seats "+ objResSys.getTotalSeats()); Thread objThread1 = new Thread(() -> {objResSys.reserveSeats("User1", 10);}); Thread objThread2 = new Thread(() -> {objResSys.reserveSeats("User2", 20);}); Thread objThread3 = new Thread(() -> {objResSys.reserveSeats("User3", 5);}); objThread1.start(); objThread2.start(); objThread3.start(); try { objThread1.join(); objThread2.join(); objThread3.join(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } System.out.println("Remaining available Seats "+ objResSys.getTotalSeats()); } }
Total available Seats 100 User2 has reserved 20 with 80 still available User1 has reserved 10 with 70 still available User3 has reserved 5 with 65 still available Remaining available Seats 65