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 void
printJob(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;
public
PrintingJob(PrinterQueue printerQueue) {
this.printerQueue = printerQueue;
}
public void
run() {
System.out.printf("%s: Going to
print a document\n",
Thread.currentThread().getName());
printerQueue.printJob(new
Object());
}
}
TestLock.java
public class TestLock {
public static void main(String[] args) {
PrinterQueue printerQueue = new
PrinterQueue();
Thread thread[] = new
Thread[10];
for (int
i = 0; i < 5; i++) {
thread[i] = new
Thread(new PrintingJob(printerQueue), "Thread " + i);
}
for (int
i = 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