Pages

Thursday, 12 May 2016

Lock API in java

A lock is a thread synchronization mechanism like synchronized blocks except locks can be more sophisticated than Java's synchronized blocks. Locks are created using synchronized blocks, so it is not like we can get totally rid of the synchronized keyword.

Lock - Base interface for Lock API:
It provides all the features of synchronized keyword with additional ways to create different Conditions for locking, providing timeout for thread to wait for lock. Some of the important methods are lock() to acquire the lock, unlock() to release the lock, tryLock() to wait for lock for a certain period of time, newCondition() to create the Condition etc.

Calling unlock() in a finally-clause
The Lock applied on the critical section and the critical section may throw exceptions, it is important to call the unlock() method from inside a finally-clause. Doing so makes sure that the Lock is unlocked so other threads can lock it.

Example of Lock in Java
PrinterQueue.java
import java.util.Date;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class PrinterQueue {
       private final Lock queueLock = new ReentrantLock();

       public voidprintJob(Object document) {
              queueLock.lock();
              try {
                     Long duration = (long) (Math.random() * 10000);
                     System.out.println(Thread.currentThread().getName() +
                                  ": PrintQueue: Prepare coffee during "
                                  +(duration / 1000) + " seconds :: Time - " + new Date());
                     Thread.sleep(duration);
              } catch (InterruptedException e) {
                     e.printStackTrace();
              } finally {
                     System.out.printf("%s: The document has been printed\n", Thread.currentThread().getName());
                     queueLock.unlock();
              }
       }
}

PrintingJob.java

class PrintingJob implements Runnable {
       private PrinterQueue printerQueue;

       publicPrintingJob(PrinterQueue printerQueue) {
              this.printerQueue = printerQueue;
       }

       public voidrun() {
              System.out.printf("%s: Going to print a document\n",
                           Thread.currentThread().getName());
              printerQueue.printJob(newObject());
       }
}

TestLock.java
public class TestLock {
       public static void main(String[] args) {
              PrinterQueue printerQueue = newPrinterQueue();
              Thread thread[] = newThread[10];
             
              for (inti = 0; i < 5; i++) {
                     thread[i] = newThread(new PrintingJob(printerQueue), "Thread " + i);
              }
             
              for (inti = 0; i < 5; i++) {
                     thread[i].start();
              }
       }
}
Output:
Thread 0: Going to print a document
Thread 3: Going to print a document
Thread 2: Going to print a document
Thread 1: Going to print a document
Thread 4: Going to print a document
Thread 0: PrintQueue: Prepare coffee during 2 seconds :: Time - Fri May 13 10:32:57 IST 2016
Thread 0: The document has been printed
Thread 3: PrintQueue: Prepare coffee during 8 seconds :: Time - Fri May 13 10:32:59 IST 2016
Thread 3: The document has been printed
Thread 2: PrintQueue: Prepare coffee during 0 seconds :: Time - Fri May 13 10:33:08 IST 2016
Thread 2: The document has been printed
Thread 1: PrintQueue: Prepare coffee during 8 seconds :: Time - Fri May 13 10:33:09 IST 2016
Thread 1: The document has been printed
Thread 4: PrintQueue: Prepare coffee during 8 seconds :: Time - Fri May 13 10:33:17 IST 2016
Thread 4: The document has been printed


Some important interfaces and classes in Java Concurrency Lock API

Condition:
Condition objects are similar to Object wait-notify model with additional feature to create different sets of wait. A Condition object is always created by Lock object. Some of the important methods are await() that is similar to wait() and signal(), signalAll() that is similar to notify() and notifyAll() methods.

ReadWriteLock:
It contains a pair of associated locks, one for read-only operations and another one for writing. The read lock may be held simultaneously by multiple reader threads as long as there are no writer threads. The write lock is exclusive.

ReentrantLock:
This is the most widely used implementation class of Lock interface. This class implements the Lock interface in similar way as synchronized keyword. Apart from Lock interface implementation, ReentrantLock contains some utility methods to get the thread holding the lock, threads waiting to acquire the lock etc.

synchronized block are reentrant in nature i.e if a thread has lock on the monitor object and if another synchronized block requires to have the lock on the same monitor object then thread can enter that code block that’s why class name to be ReentrantLock.


No comments:

Post a Comment