In previous post, we discussed about Pros and Cons of Lock (java.util.concurrent.locks) over synchronized methods and statements and concluded that Lock interface provides high programmatic control and some times efficient too.The main agenda of this post is to create a custom ReentrantLock class by implementing Lock interface and use that custom class to show case an ticket booking use case where lock is acquired and released using lock() and unlock() method respectively.
Java doc of Lock interface discusses about three forms of lock acquisition (interruptible, non-interruptible, and timed), however for sake of simplicity we assume that no thread will be interrupted and we will just focus on syntax and semantics of lock() and unlock() method. Lets create a custom lock interface consisting of three methods as follows:-
Explanation:- lockHoldCount is a instance variable of class implementing lock interface. If lock() method is called from context of any thread and lockHoldCount value is 0 then lockHoldCount is incremented and if lockHoldCount value is non-zero and lock has been already acquired by the calling thread then hold count is incremented(chain locking). Otherwise, thread has to wait until other treads executes notify() method and releases lock.
Explanation:- Decrement lockHoldCount if it is greater than zero, else throw exception IllegalMonitorStateException (It indicates, lock was not acquired and thread is trying to release it).
=====================Sample output====================
Waiting to book ticket : Passanger-1 Nikhil
Ticket booking started for : Passanger-1 Nikhil
Waiting to book ticket : Passanger-2 Ranjan
Waiting to book ticket : Passanger-5 Ritz
Waiting to book ticket : Passanger-3 Yunnus
Waiting to book ticket : Passanger-4 CKM
Congratulation!!, Ticket BOOKED successfully for : Passanger-1 Nikhil
currently ticketsAvailable = 2
Ticket booking started for : Passanger-2 Ranjan
Congratulation!!, Ticket BOOKED successfully for : Passanger-2 Ranjan
currently ticketsAvailable = 1
Ticket booking started for : Passanger-5 Ritz
Congratulation!!, Ticket BOOKED successfully for : Passanger-5 Ritz
currently ticketsAvailable = 0
Sorry!! Ticket NOT BOOKED for : Passanger-3 Yunnus. Current booking status is Waiting list(W/L): 1
Sorry!! Ticket NOT BOOKED for : Passanger-4 CKM. Current booking status is Waiting list(W/L): 2
=====================================================
Explanation:- The constructor of class TicketBookingIRCTC initializes ticketsAvailable to 3 and main threads spawn five threads for booking three tickets, depending on OS which thread scheduled first - calls lock method and acquire lock, book ticket and decrement ticketsAvailable count.
Java doc of Lock interface discusses about three forms of lock acquisition (interruptible, non-interruptible, and timed), however for sake of simplicity we assume that no thread will be interrupted and we will just focus on syntax and semantics of lock() and unlock() method. Lets create a custom lock interface consisting of three methods as follows:-
/*
* For sake of simplicity - assume custom lock interface having only three
* methods.
*/
interface CustomLock {
public void lock();
public boolean tryLock();
public void unlock();
}
lock() method sample code:-
/*lock method implementation of CustomLock interface*/
public synchronized void lock() {
/*
* Acquires the lock if it is not held by another thread and set lock
* hold count to 1.
*/
if (lockHoldCount == 0) {
lockHoldCount++;
threadId = Thread.currentThread().getId();
}
/*
* If current thread already holds lock then hold count is increased by
* 1 - Chain locking.
*/
else if (lockHoldCount > 0
&& threadId == Thread.currentThread().getId()) {
lockHoldCount++;
}
// If the lock is held by another thread then the current
// thread waits for another thread to release lock.
else {
try {
wait();
lockHoldCount++;
threadId = Thread.currentThread().getId();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
unlock() method sample code:-
/*unlock method is executed to release lock*/
public synchronized void unlock() {
/*
* If current thread is not holding the lock, if unlock is called it
* throws IllegalMonitorStateException.
*/
if (lockHoldCount == 0)
throw new IllegalMonitorStateException();
/* If lock is held, decrement lock hold count by 1 */
lockHoldCount--;
/*
* If lockHoldCount is 0, lock is released and waiting thread is
* notified.
*/
if (lockHoldCount == 0)
notify();
}
trylock() method sample code:-
/*tryLock method returns true if lock is available and calls lock() interanlly*/
public synchronized boolean tryLock() {
/*
* Acquires the lock if it is not held by another thread and // returns
* true
*/
if (lockHoldCount == 0) {
lock();
return true;
}
// If lock is held by another thread then method return false.
else
return false;
}
Concrete customReentrantLock class implementing CustomLock interface:-
Create a class file name it as CustomReentrantLock.java and copy/paste following sample code lines./** * http://www.devinline.com */ package com.devinline.locking; /* * For sake of simplicity - assume custom lock interface having only three * methods. */ interface CustomLock { public void lock(); public boolean tryLock(); public void unlock(); } public class CustomReentrantLock implements CustomLock { /* Maintain number of locks acquired by a thread */ int lockHoldCount; /* Id of thread which is currently holding the lock. */ long threadId; /** * Creates an instance of CustomReentrantLock and Initial lock hold count is * 0. */ CustomReentrantLock() { lockHoldCount = 0; } @Override public synchronized void lock() { /* * Acquires the lock if it is not held by another thread and set lock * hold count to 1. */ if (lockHoldCount == 0) { lockHoldCount++; threadId = Thread.currentThread().getId(); } /* * If current thread already holds lock then hold count is increased by * 1 - Chain locking. */ else if (lockHoldCount > 0 && threadId == Thread.currentThread().getId()) { lockHoldCount++; } // If the lock is held by another thread then the current // thread waits for another thread to release lock. else { try { wait(); lockHoldCount++; threadId = Thread.currentThread().getId(); } catch (InterruptedException e) { e.printStackTrace(); } } } @Override public synchronized void unlock() { /* * If current thread is not holding the lock, if unlock is called it * throws IllegalMonitorStateException. */ if (lockHoldCount == 0) throw new IllegalMonitorStateException(); /* If lock is held, decrement lock hold count by 1 */ lockHoldCount--; /* * If lockHoldCount is 0, lock is released and waiting thread is * notified. */ if (lockHoldCount == 0) notify(); } @Override public synchronized boolean tryLock() { /* * Acquires the lock if it is not held by another thread and // returns * true */ if (lockHoldCount == 0) { lock(); return true; } // If lock is held by another thread then method return false. else return false; } }
Ticket booking use case implementation - use lock()/unlock() of CustomReentrantLock
The main goal of this use case is to use CustomReentrantLock class for acquiring and releasing lock while multiple threads are trying for some shared scarce resources. Below is the driver program which creates 5 threads(customer for ticket booking) and these 5 threads will try to acquire lock and book a ticket, out of 5 only 3 threads will be able to book ticket successfully(Since only 3 tickets are available).package com.devinline.locking;
public class TicketBookingDriverProgram {
public static void main(String[] args) {
CustomLock customLock = new CustomReentrantLock();
TicketBookingIRCTC myRunnable = new TicketBookingIRCTC(customLock, 3);
new Thread(myRunnable, "Passanger-1 Nikhil").start();
new Thread(myRunnable, "Passanger-2 Ranjan").start();
new Thread(myRunnable, "Passanger-3 Yunnus").start();
new Thread(myRunnable, "Passanger-4 CKM").start();
new Thread(myRunnable, "Passanger-5 Ritz").start();
}
}
class TicketBookingIRCTC implements Runnable {
int ticketsAvailable; // scarce resource
CustomLock customLock;
public TicketBookingIRCTC(CustomLock customLock, int totalTicket) {
this.customLock = customLock;
ticketsAvailable = totalTicket;
}
public void run() {
System.out.println("Waiting to book ticket : "
+ Thread.currentThread().getName());
/* get hold of lock for booking ticket */
customLock.lock();
if (ticketsAvailable > 0) {
System.out.println("Ticket booking started for : "
+ Thread.currentThread().getName());
// Ticket booking time is 2 sec, so sleep for 2sec
try {
Thread.sleep(1000);
} catch (Exception e) {
}
/* Update available ticket count */
ticketsAvailable--;
System.out.println("Congratulation!!, Ticket BOOKED "
+ "successfully for : " + Thread.currentThread().getName());
System.out.println("currently ticketsAvailable = "
+ ticketsAvailable);
} else {
ticketsAvailable--;
System.out.println("Sorry!! Ticket NOT BOOKED for : "
+ Thread.currentThread().getName()
+ ". Current booking status is Waiting list(W/L): "
+ Math.abs(ticketsAvailable));
}
customLock.unlock();
}
}
Waiting to book ticket : Passanger-1 Nikhil
Ticket booking started for : Passanger-1 Nikhil
Waiting to book ticket : Passanger-2 Ranjan
Waiting to book ticket : Passanger-5 Ritz
Waiting to book ticket : Passanger-3 Yunnus
Waiting to book ticket : Passanger-4 CKM
Congratulation!!, Ticket BOOKED successfully for : Passanger-1 Nikhil
currently ticketsAvailable = 2
Ticket booking started for : Passanger-2 Ranjan
Congratulation!!, Ticket BOOKED successfully for : Passanger-2 Ranjan
currently ticketsAvailable = 1
Ticket booking started for : Passanger-5 Ritz
Congratulation!!, Ticket BOOKED successfully for : Passanger-5 Ritz
currently ticketsAvailable = 0
Sorry!! Ticket NOT BOOKED for : Passanger-3 Yunnus. Current booking status is Waiting list(W/L): 1
Sorry!! Ticket NOT BOOKED for : Passanger-4 CKM. Current booking status is Waiting list(W/L): 2
=====================================================
Explanation:- The constructor of class TicketBookingIRCTC initializes ticketsAvailable to 3 and main threads spawn five threads for booking three tickets, depending on OS which thread scheduled first - calls lock method and acquire lock, book ticket and decrement ticketsAvailable count.
Most valuable article. Really I got more knowledge from this article. Thanks.
ReplyDeletePlacement Training in Chennai
Placement Training centres in Chennai
Placement Training in Tambaram
soft skills training in chennai
best soft skills training in chennai
clinical sas training in chennai
SAS Training in Chennai
Liên hệ Aivivu, đặt vé máy bay tham khảo
ReplyDeletevé máy bay đi Mỹ giá bao nhiêu
hướng dẫn đi máy bay từ mỹ về việt nam
thông tin chuyến bay từ canada về việt nam
đặt vé máy bay từ nhật về việt nam
vé máy bay hàn quốc hà nội
Vé máy bay từ Đài Loan về VN
danh sách khách sạn cách ly tại tphcm