StampedLock
Learn how to use the StampedLock class for optimistic read, write and read access.
We'll cover the following...
If you are interviewing, consider buying our number#1 course for Java Multithreading Interviews.
Code widgets in this lesson may fail to execute, if Educative.io’s code execution platform doesn’t use Java version 9 or above. This is because the
StampedLock
class was introduced in Java 9.
Overview
The StampedLock
was introduced in Java 9 and is a capability-based lock with three modes for controlling read/write access.
The StampedLock
class is designed for use as an internal utility in the development of other thread-safe components. Its use relies on knowledge of the internal properties of the data, objects, and methods it protects.
Modes
The state of a StampedLock
is defined by a version and mode. There are three modes the lock can be in:
- Writing
- Reading
- Optimistic Reading
On acquiring a lock, a stamp (long value) is returned that represents and controls access with respect to a lock state. The stamp can be used later on to release the lock or convert the existing acquired lock to a different mode.
Reading
The read mode can be acquired using the readLock()
method. When reading a thread isn’t expected to make any changes to the shared state and therefore it makes sense to have multiple threads acquire the read lock at the same time. The method returns a stamp that can be used to unlock the read lock. Timed and untimed versions of tryReadLock()
also exist.
The code widget below demonstrates multiple threads acquiring the StampedLock
in read mode.
import java.util.concurrent.*;class Demonstration {public static void main( String args[] ) {ExecutorService executorService = Executors.newFixedThreadPool(10);// create an instance of StampedLockStampedLock stampedLock = new StampedLock();// main thread attempts to acquire the lock twice, which is grantedlong readStamp1 = stampedLock.readLock();long readStamp2 = stampedLock.readLock();try {// create 3 threadsfor (int i = 0; i < 3; i++) {executorService.submit(new Runnable() {@Overridepublic void run() {try {long readStamp = stampedLock.readLock();System.out.println("Read lock count in spawned thread " + stampedLock.getReadLockCount());// simulate thread performing read of shared statetry {Thread.sleep(2000);} catch (InterruptedException ie) {// ignore} finally {stampedLock.unlockRead(readStamp);}} catch (Exception e) {System.out.println(e);}}});}// let the main thread simulate work for 5 secondsThread.sleep(5000);} finally {// wait for spawned threads to finishexecutorService.shutdown();executorService.awaitTermination(1, TimeUnit.HOURS);// remember to unlockstampedLock.unlock(readStamp1);stampedLock.unlock(readStamp2);}System.out.println("Read lock count in main thread " + stampedLock.getReadLockCount());System.out.println("stampedLock.isReadLocked() " + stampedLock.isReadLocked());}}
While read lock is held by a reader thread, all attempts to acquire the write lock will be blocked.
Writing
The write mode can be acquired by invoking the writeLock()
method. When the write lock is held, all threads attempting to acquire the read lock will be blocked. Similar to the read lock, timed and untimed versions of tryWriteLock()
exist. The following widget demonstrates the use of the write lock:
import java.util.concurrent.*;class Demonstration {public static void main( String args[] ) {ExecutorService executorService = Executors.newFixedThreadPool(10);// create an instance of StampedLockStampedLock stampedLock = new StampedLock();// main thread acquires the write lock before spawning read threadlong stamp = stampedLock.writeLock();try {executorService.submit(new Runnable() {@Overridepublic void run() {System.out.println("Attempting to acquire read lock");long readStamp = stampedLock.readLock();System.out.println("Read lock acquired");stampedLock.unlock(readStamp);}});// Having the thread sleep for 3 seconds so that the read thread// gets blockedThread.sleep(3000);} finally {// unlock writeSystem.out.println("Write lock being released");stampedLock.unlock(stamp);// wait for read thread to exitexecutorService.shutdown();executorService.awaitTermination(1, TimeUnit.HOURS);}}}
In the above program, the print statement for releasing the write lock is always output before the statement for acquiring the read lock.
Remember that the ...