In order to apply locks explicitly, an instance of the Lock interface needs to be created which is defined in the java.util.concurrent. Locks package. Using the Lock interface is similar to using the synchronized keyword. The Lock interface provides lock () and unlock () methods to acquire and release the lock respectively.
In order to synchronize a method, call the Lock’s lock () method at the start of the method to acquire a lock and the Lock’s unlock () method at the end of the method to release the lock. Once the thread acquires a lock, other threads that attempt to acquire a lock on the same object will have to wait until the current thread calls the unlock () method to release the lock.
import java.util.concurrent.locks.Lock; //import Lock interface import java.util.concurrent.locks.ReentrantLock; // import ReentrantLock class class Account { private double balance=5000; private Lock lockObj = new ReentrantLock(); //Create a lock public double getBalance() { return balance; } public void deposit(double amount ) { lockObj.lock(); //lock his object try { System.out.println( Thread.currentThread().getName() +" Read Balance : " + balance); double newBalance = balance + amount; Thread.sleep(1000); balance = newBalance; } catch(InterruptedException ex){} finally { lockObj.unlock(); //unlock this 0bject } } } class AddAmountTask implements Runnable { Account acct; AddAmountTask(Account ac) { acct = ac; } public void run() { acct.deposit(100); } } class ExlicitLock { public static void main(String[] args) { Account a = new Account(); //shared resource AddAmountTask t = new AddAmountTask(a); Thread t1 = new Thread(t); Thread t2 = new Thread(t); Thread t3 = new Thread(t); t1.start(); t2.start(); t3.start(); try { t1.join(); t2.join(); t3.join(); } catch(InterruptedException ex){} System.out.println("Total Balance in Account is : " + a.getBalance()); } }
This program demonstrates the updation of bank balance using the explicit locking.
The statements.
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
imports the Lock interface and ReentrantLock class to use lock () and unlock () methods and creating locks respectively. The statement,
private Lock lockObj= new ReentrantLock();
creates an object of type ReenterantLock () and assigns its reference to lockObj. The class ReenterantLock is a basic implementation of Lock interface for creating mutually exclusive locks. This class has two constructors.
• public Reenterantlock (boolean fair): Creates an instance of ReenterantLock with the given fairness policy. If the boolean argument fair is set to true, the longest waitingthread will acquire the lock when it is available otherwise there is no guarantee as to whichwaiting thread will acquire the lock when it is available.
• public ReenterantLock ():Creates an instance of Reenterantlock. It is equivalent to using ReenterantLock (false).
When the thread’s run () method is called it inturn invokes the deposi t () method of the Account object. In this method, the associated thread tries to acquire a lock using the statement.
lockobj.lock();
If the lock is available (i.e. no other thread has acquired this lock), method lock () will return immediately (i.e. thread acquires a lock) and thread will continue. If the lock is unavailable, this method will wait until the lock is selected by other thread by calling the Lock’s unlock () method.
Note that immediately following the lock () method call is a try-catch block and unlock () method call is placed in the finally block. This is done so as to ensure that this lock is always released.