Showing posts with label lock. Show all posts
Showing posts with label lock. Show all posts

Monday, May 20, 2024

Java ReentrantReadWriteLock With Examples

This post gives an introduction to ReadWriteLock interface and it's implementing class ReentrantReadWriteLock in Java with usage examples.


ReadWriteLock in Java

Even in a multi-threading application multiple reads can occur simultaneously for a shared resource. It is only when multiple writes happen simultaneously or intermix of read and write that there is a chance of writing the wrong value or reading the wrong value.

ReadWriteLock in Java uses the same idea in order to boost the performance by having separate pair of locks. A ReadWriteLock maintains a pair of associated locks-

  • One for read-only operations; and
  • one for writing.

The read lock may be held simultaneously by multiple reader threads, so long as there are no writers. The write lock is exclusive.

Having a pair of read-write lock allows for a greater level of concurrency in accessing shared data than that permitted by a mutual exclusion lock. It exploits the fact that while only a single thread at a time (a writer thread) can modify the shared data, in many cases any number of threads can concurrently read the data (hence reader threads).

A read-write lock will improve performance over the use of a mutual exclusion lock if the frequency of reads is more than writes, duration of the read operations is more than the duration of the writes. It also depends on the contention for the data - that is, the number of threads that will try to read or write the data at the same time.

For example, a collection that is initially populated with data and thereafter infrequently modified, while being frequently searched (such as a directory of some kind) is an ideal candidate for the use of a read-write lock. However, if updates become frequent then the data spends most of its time being exclusively locked and there is little, if any increase in concurrency.

ReentrantReadWriteLock class in Java

As already mentioned ReentrantReadWriteLock is an implementation of the ReadWriteLock interface which provides a pair of read-write lock. ReentrantReadWriteLock has similar semantics to ReentrantLock in Java.

ReentrantReadWriteLock class in Java does not impose a reader or writer preference ordering for lock access which means there is no acquisition preference. Though there is an optional fairness policy. A ReentrantReadWriteLock is fair or not is specified in its constructor.

ReentrantReadWriteLock in Java allows both read and write locks to reacquire read and write locks in the same fashion as done in Reentrant lock. See an example here.

Java ReentrantReadWriteLock constructors

  • ReentrantReadWriteLock()- Creates a new ReentrantReadWriteLock with default (nonfair) ordering properties.
  • ReentrantReadWriteLock(boolean fair)- Creates a new ReentrantReadWriteLock with the given fairness policy.

Fair mode in ReentrantReadWriteLock

When constructed as fair, threads contend for entry using an approximately arrival-order policy. When the currently held lock is released, either the longest-waiting single writer thread will be assigned the write lock, or if there is a group of reader threads waiting longer than all waiting writer threads, that group will be assigned the read lock.

Lock downgrading in ReentrantReadWriteLock

ReentrantReadWriteLock also allows downgrading from the write lock to a read lock. You can first acquire a write lock, then the read lock and then release the write lock. So you are effectively left with a read lock. However, upgrading from a read lock to the write lock is not possible.

Example of lock downgrading

If you have a scenario where you want to read from a cache only if it is still valid, using a read lock. If cache is dirty then you need to acquire a write lock and put data in the cache again.

import java.util.concurrent.locks.ReentrantReadWriteLock;

public class ReentrantDowngrade {
  Object data;
  volatile boolean cacheValid;
  ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();

  void processCacheData(){
    // first acquire a read lock
    rwl.readLock().lock();
    // check if cache is still valid
    if (!cacheValid) {
      // Must release read lock before acquiring 
      // write lock, as upgrading not possible
      rwl.readLock().unlock();
      rwl.writeLock().lock();
      try {
        // Recheck state because another thread might have
        // acquired write lock and changed state before we did.
        if (!cacheValid) {
          // get fresh data for the cache
          data = ...
          cacheValid = true;
        }
        // Downgrade by acquiring read lock before 
        // releasing write lock
        rwl.readLock().lock();
      } finally {
        // Unlock write, still hold read
        rwl.writeLock().unlock(); 
      }
    }
    try {
      // use cache data
      use(data);
    } finally {
      // Finally release the read lock
      rwl.readLock().unlock();
    }
  }
}

ReentrantReadWriteLock Java example

Let us see another example where two threads are using the read lock and one write lock. In class ReentrantRWDemo there are two methods, get() is used to get data from the TreeMap, so read lock is used. Another method put() is used to add value to a map and uses the write lock.

There are 2 classes ReadThread which is used for reader threads and another class WriterThread is used for write threads. In the program two reader thread and one writer thread are spawned.

public class ReentrantRWDemo {
  private final Map<String, String> m = new TreeMap<String, String>();
  private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
    
  // get method for getting values from map
  // it can be used by many read threads simultaneously
  public String get(String key) {
    System.out.println("In get method waiting to acquire lock");
    rwl.readLock().lock();
    System.out.println("In get method acquired read lock");
    try { 
      try {
        Thread.sleep(1500);
      } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
      return m.get(key); 
    }
    finally { 
      rwl.readLock().unlock(); 
      System.out.println("In get method released read lock");
    }
  }
    
  // Put method to store  key, value in a map
  // it acquires a write lock so only one thread at a time
  public String put(String key, String value) {
    System.out.println("In put method waiting to acquire lock");
    rwl.writeLock().lock();
    System.out.println("In put method acquired write lock");
    try { 
      try {
        Thread.sleep(1000);
      } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
      return m.put(key, value); 
    }
    finally { 
      rwl.writeLock().unlock(); 
      System.out.println("In put method released write lock");
    }
  }
    
  public void display(){
    m.entrySet().forEach(System.out::println);
      
  }
    
  public static void main(String... args) {
    ReentrantRWDemo rwDemo = new ReentrantRWDemo();
    // Putting some values in the map
    rwDemo.put("1", "One");
    rwDemo.put("2", "Two");
    rwDemo.put("3", "Three");
    
    // Starting two read threads and one write thread
    Thread rThread1 = new Thread(new ReadThread(rwDemo));
    Thread wThread = new Thread(new WriterThread(rwDemo));
    Thread rThread2 = new Thread(new ReadThread(rwDemo));
    rThread1.start();
    wThread.start();
    rThread2.start();
    // Wait for the threads to finish, then only go for display method
    try {
      rThread1.join();
      wThread.join();
      rThread2.join();
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }    
    rwDemo.display();        
  }
}

class ReadThread implements Runnable {
  ReentrantRWDemo rwDemo;
  ReadThread(ReentrantRWDemo rwDemo){
    this.rwDemo = rwDemo;
  }
  public void run() {
    System.out.println("Value - " + rwDemo.get("1"));
  }
}

class WriterThread implements Runnable {
  ReentrantRWDemo rwDemo;
  WriterThread(ReentrantRWDemo rwDemo){
    this.rwDemo = rwDemo;
  }
  public void run() {
    rwDemo.put("4", "Four");
  }
}

Output

In put method waiting to acquire lock
In put method acquired write lock
In put method released write lock
In put method waiting to acquire lock
In put method acquired write lock
In put method released write lock
In put method waiting to acquire lock
In put method acquired write lock
In put method released write lock
In get method waiting to acquire lock
In put method waiting to acquire lock
In put method acquired write lock
In get method waiting to acquire lock
In put method released write lock
In get method acquired read lock
In get method acquired read lock
In get method released read lock
Value - One
In get method released read lock
Value - One
1=One
2=Two
3=Three
4=Four

Here you can ignore the first three set of put prints as these are the messages for the first 3 puts that are used to add values to the TreeMap. As mentioned two reader threads and one writer thread are spawned. In the display I got (for you it may vary) it can be seen that write thread first locks the shared object rwDemo, though Thread.sleep is used to introduce some delay but the reader threads will wait until the write lock is released.

But both read locks can acquire lock simultaneously as confirmed by two consecutive "In get method acquired read lock" statement.

Also note that in display() method, method reference with lambda expression is used to display the map values. These features are available from Java 8.

Thread's join method is used so that values are displayed once all the threads have finished.

That's all for this topic Java ReentrantReadWriteLock With Examples. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Difference Between ReentrantLock and Synchronized in Java
  2. Java StampedLock With Examples
  3. Java CountDownLatch With Examples
  4. CopyOnWriteArrayList in Java With Examples
  5. Java Concurrency Interview Questions And Answers

You may also like-

  1. Executor And ExecutorService in Java With Examples
  2. Inter-thread Communication Using wait(), notify() And notifyAll() in Java
  3. Race Condition in Java Multi-Threading
  4. How and Why to Synchronize ArrayList in Java
  5. equals() And hashCode() Methods in Java
  6. Java Program to Convert a File to Byte Array
  7. @FunctionalInterface Annotation in Java
  8. Spliterator in Java

Thursday, May 2, 2024

Java ReentrantLock With Examples

java.util.concurrent.locks package has added support for locks, which provides an alternative to using Synchronized in Java in scenarios where we need to control access to a shared resource. In this post we'll talk about one of the concrete implementation of the lock interface called ReentrantLock in Java. There is another implementation ReentrantReadWriteLock which is implementation of ReadWriteLock interface.

ReentrantLock was added in Java 5 along with other concurrent features like CyclicBarrier, ConcurrentHashMap, CopyOnWriteArrayList with in java.util.Concurrent package, to develop concurrent applications.


What is ReentrantLock and why needed

ReentrantLock class in Java is a concrete implementation of the Lock interface which is present in java.util.concurrent.locks package. One question which comes to mind is why this separate functionality for locking is needed when there already is Synchronized keyword in Java which provides the same functionality.

As you must be knowing every object created in Java has one mutually exclusive lock associated with it. When you are using synchronized you are using that lock implicitly (with no other feature) whereas when you are using any of the lock implementation (like ReentrantLock) you are using that lock explicitly. Which means there are methods like lock() to acquire the lock and unlock() to release the lock. Along with that ReentrantLock in Java provides many other features like fairness, ability to interrupt and a thread waiting for a lock only for a specified period.

According to the Java docs "ReentrantLock is a reentrant mutual exclusion Lock with the same basic behavior and semantics as the implicit monitor lock accessed using synchronized methods and statements, but with extended capabilities."

Why is it called ReentrantLock

It is called ReentrantLock as there is an acquisition count associated with the lock which means when you use lock() method to acquire a lock and you get it then the acquisition count is 1.

A Reentrant lock will also allow the lock holder to enter another block of code with the same lock object as thread already owns it. In that case, if a thread that holds the lock acquires it again, the acquisition count is incremented and the lock then needs to be released twice to truly release the lock. Let's see it with an example to make it clear-

Here two threads are created. In the run method of the thread class methodA() is called which uses the same lock object to control access. So you will see two things here-

  • Whichever thread acquires the lock will also be able to access methodA() critical section as it already holds the lock. Only thing is acquisition count will become 2.
  • Since in the methodA(), unlock() method is not used to release the lock (remember we need to release it twice as acquisition count is 2). So another thread will never get a chance to acquire a lock.
public class ReentrantDemo {
  public static void main(String[] args) {
    ReentrantLock rLock = new ReentrantLock();
    Thread t1 = new Thread(new Display("Thread-1", rLock));
    Thread t2 = new Thread(new Display("Thread-2", rLock));
    System.out.println("starting threads ");
    t1.start();
    t2.start();
  }
}

class Display implements Runnable {
  private String threadName;
  ReentrantLock lock;
  Display(String threadName, ReentrantLock lock){
    this.threadName = threadName;
    this.lock = lock;
  }
  @Override
  public void run() {
    System.out.println("In Display run method, thread " + threadName + 
     " is waiting to get lock");
    //acquiring lock
    lock.lock();
    try {
      System.out.println("Thread " + threadName + "has got lock");
      methodA();
    } finally{
      lock.unlock();
    }        
  }
    
  public void methodA(){
    System.out.println("In Display methodA, thread " + threadName + 
      " is waiting to get lock");
    //try {        
      lock.lock();      
      System.out.println("Thread " + threadName + "has got lock");
      System.out.println("Count of locks held by thread " + threadName + 
       " - " + lock.getHoldCount());
      // Not calling unlock
      /*} finally{
      lock.unlock();
    }*/
  }    
}

Output

starting threads 
In Display run method, thread Thread-1 is waiting to get lock
In Display run method, thread Thread-2 is waiting to get lock
Thread Thread-1has got lock
In Display methodA, thread Thread-1 is waiting to get lock
Thread Thread-1has got lock
Count of locks held by thread Thread-1 - 2

Here it can be seen that both thread starts and Thread-1 acquires a lock, Thread-1 will acquire the same lock again in methodA() but there it is not released. You can notice the method lock.getHoldCount() which gives the count of holds on this lock by the current thread. Since unlock() method is not called so lock is never released that is why Thread-2 never gets a chance to acquire a lock. You can see it never goes beyond this message "In Display run method, thread Thread-2 is waiting to get lock".

Note that in different runs thread which acquires a lock may vary.

Now let's correct the code and use the unlock() method to release the lock and see what happens.

public class ReentrantDemo {
  public static void main(String[] args) {
    ReentrantLock rLock = new ReentrantLock();
    Thread t1 = new Thread(new Display("Thread-1", rLock));
    Thread t2 = new Thread(new Display("Thread-2", rLock));
    System.out.println("starting threads ");
    t1.start();
    t2.start();
  }
}

class Display implements Runnable {
  private String threadName;
  ReentrantLock lock;
  Display(String threadName, ReentrantLock lock){
    this.threadName = threadName;
    this.lock = lock;
  }
  @Override
  public void run() {
    System.out.println("In Display run method, thread " + threadName + 
     " is waiting to get lock");
    //acquiring lock
    lock.lock();
    try {
      System.out.println("Thread " + threadName + "has got lock");
      methodA();
    } finally{
      lock.unlock();
    }      
  }
    
  public void methodA(){
    System.out.println("In Display methodA, thread " + threadName 
     + " is waiting to get lock");
    //acquiring lock
    lock.lock();
    try {
      System.out.println("Thread " + threadName + "has got lock");
      System.out.println("Count of locks held by thread " + threadName 
       + " - " + lock.getHoldCount());
    } finally{
      lock.unlock();
    }
  }  
}

Output

starting threads 
In Display run method, thread Thread-1 is waiting to get lock
In Display run method, thread Thread-2 is waiting to get lock
Thread Thread-1has got lock
In Display methodA, thread Thread-1 is waiting to get lock
Thread Thread-1has got lock
Count of locks held by thread Thread-1 - 2
Thread Thread-2has got lock
In Display methodA, thread Thread-2 is waiting to get lock
Thread Thread-2has got lock
Count of locks held by thread Thread-2 - 2

Now both threads are able to run as the locks are properly release after acquiring.

Convention while using ReentrantLock in Java

If you had noticed one thing in the above code lock.lock() method is always called before the try block. When you are using Reentrantlock in Java, it is a recommended practice to always immediately follow a call to lock with a try block.

If you will call lock() method with in the try block and some thing goes wrong while acquiring the lock finally block will still be called and there you will have lock.unlock() method. So you will end up unlocking the lock which was never acquired and that will result in IllegalMonitorStateException, that’s why it is recommended to call lock() method before try block.

At the same time you do want to unlock the acquired lock if something goes wrong after acquiring the lock, that is why immediately follow a call to lock with try block.

Features of ReentrantLock in Java

ReentrantLock provides many features like fairness, ability to interrupt and a thread waiting for a lock only for a specified period. Let's have a look at some of these features.

  1. Fairness- ReentrantLock has one constructor which takes boolean value as an argument. That lets you choose whether you want a fair or an unfair lock depending upon whether the boolean value is true or false. A fair lock is one where the threads acquire the lock in the same order they asked for it; whereas in case of an unfair lock a thread can sometimes acquire a lock before another thread that asked for it first.
  2. public ReentrantLock(boolean fair)
    
  3. Lock interruptibly- ReentrantLock provides a method lockInterruptibly, where the thread acquires a lock if it is not interrupted.
    public void lockInterruptibly() throws InterruptedException
     
  4. Ability to check if the lock is being held- ReentrantLock in Java provides ability to check if the lock is already being held using tryLock() method.

    tryLock()- Acquires the lock only if it is not held by another thread at the time of invocation.

    tryLock(long timeout, TimeUnit unit) - Acquires the lock if it is not held by another thread within the given waiting time and the current thread has not been interrupted.

  5. Some of the other methods in ReentrantLock class are as follows-
    • getHoldCount()- Queries the number of holds on this lock by the current thread.
    • getWaitingThreads(Condition condition) - Returns a collection containing those threads that may be waiting on the given condition associated with this lock.
    • isHeldByCurrentThread()- Queries if this lock is held by the current thread.
    • isLocked()- Queries if this lock is held by any thread.

Drawbacks of ReentrantLock in Java

  1. Need to wrap lock acquisitions in a try/finally block and release the lock in finally block. Otherwise, if the critical section code threw an exception, the lock might never be released.
  2. Need to call unlock() method explicitly. Forgetting to do that will result in lock never getting released which will create a lots of problem and make it very hard to detect performance problems.
    With synchronization, the JVM ensures that locks are automatically released.

ReentrantLock Java example code

Let us see one more example of Reentrant lock where a resource is shared between two threads and the access is controlled using locks.

Thread.sleep is used to induce some delay, in that case also another thread won't break in. Only when the unlock() method is called and the lock is released other thread gets a chance.

import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockDemo {
  public static void main(String[] args) {
    ReentrantLock rLock = new ReentrantLock();
    Thread t1 = new Thread(new Counter("Thread-1", rLock));
    Thread t2 = new Thread(new Counter("Thread-2", rLock));
    System.out.println("starting threads ");
    t1.start();
    t2.start();
  }
}

// Shared class for threads
class SharedResource{
  static int count = 0;
}

class Counter implements Runnable {
  private String threadName;
  ReentrantLock lock;
  Counter(String threadName, ReentrantLock lock){
    this.threadName = threadName;
    this.lock = lock;
  }
  @Override
  public void run() {
    System.out.println("In Counter run method, thread " + threadName 
    + " is waiting to get lock");
    // acquiring the lock
    lock.lock();
    try {
      System.out.println("Thread " + threadName + " has got lock");
      SharedResource.count++;
      System.out.println("Thread " + threadName + 
       " Count " + SharedResource.count);
      try {
        Thread.sleep(500);
      } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    } finally{
      System.out.println("Thread " + threadName 
       + " releasing lock");
      // releasing the lock
      lock.unlock();
    }    
  }
}

Output

starting threads 
In Counter run method, thread Thread-1 is waiting to get lock
In Counter run method, thread Thread-2 is waiting to get lock
Thread Thread-1 has got lock
Thread Thread-1 Count 1
Thread Thread-1 releasing lock
Thread Thread-2 has got lock
Thread Thread-2 Count 2
Thread Thread-2 releasing lock

Points to remember

  • ReentrantLock in Java is a reentrant mutual exclusion Lock with the same basic behavior and semantics as the implicit monitor lock accessed using synchronized methods with some extended features.
  • Some of these features include fairness, ability to interrupt and a thread waiting for a lock only for a specified period.
  • Thread which is currently holding a lock can repeatedly enter the same lock, acquisition count increments as many times current thread acquires the same lock.
  • lock has to be released as many times as it has been acquired.
  • Failure to call unlock() as many times as the lock is acquired will result is lock not being released and the thread will continue to hold it.
  • unlock() method should be called in a finally block. Otherwise, if the critical section code threw an exception, the lock might never be released

That's all for this topic Java ReentrantLock With Examples. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. ConcurrentHashMap in Java With Examples
  2. Java StampedLock With Examples
  3. Difference Between CountDownLatch And CyclicBarrier in Java
  4. Java Phaser With Examples
  5. Java Concurrency Interview Questions And Answers

You may also like-

  1. Race Condition in Java Multi-Threading
  2. Why wait(), notify() And notifyAll() Methods Are in Object Class And Not in Thread Class
  3. How to Remove Duplicate Elements From an ArrayList in Java
  4. How to Sort elements in different order in TreeSet
  5. Difference Between Comparable and Comparator in Java
  6. @FunctionalInterface Annotation in Java
  7. Java Stream API Tutorial
  8. Dependency Injection in Spring Framework

Saturday, November 13, 2021

Difference Between ReentrantLock and Synchronized in Java

From Java 5 new lock implementations have been provided like ReentrantLock, ReentrantReadWriteLock which provide more extensive locking operations than can be obtained using synchronized methods and statements. In this post we'll see in detail what extended functionality is provided by ReentrantLock and what are the differences between ReentrantLock and synchronized in Java.

According to the Java docs

"ReentrantLock is a reentrant mutual exclusion Lock with the same basic behavior and semantics as the implicit monitor lock accessed using synchronized methods and statements, but with extended capabilities."

ReentrantLock Vs Synchronized in Java

  1. When you use a synchronized block or method you just need to write synchronized keyword (and provide associated object) acquiring lock and releasing it is done implicitly.
    With ReentrantLock acquiring and releasing lock is done by user using lock() and unlock() methods.
  2. Prescribed way to use RentrantLock in Java is to use a try-finally block. Call to lock should immediately be followed with a try block and lock should be released in finally block. That way lock will be released even if exception is thrown in critical section code.

    lock.lock();
    try {    
      //…method body    
    }finally {
      lock.unlock();
    }
     
    With Synchronized there is no such compulsion as acquiring and releasing is done implicitly.
    Synchronized(myObj){
      …
      …
    }
     
    Thus making the code written with Synchronized much cleaner and easy to read.
  3. Synchronized keyword forces all lock acquisitions and releases to occur in a block-structured way which means when multiple locks are acquired they must be released in the opposite order, and all locks must be released in the same lexical scope in which they were acquired.

    ReentrantLock provides more flexibility, it allows a lock to be acquired and released in different scopes, and allowing multiple locks to be acquired and released in any order.

    With ReentrantLock the below code is possible but not with synchronized.
    private ReentrantLock lock;
    public void methodA() {
      ...
      lock.lock();
      ...
    }
    
    public void methodB() {
      ...
      lock.unlock();
      ...
    }
    
  4. ReentrantLock provides additional functionality over the use of synchronized methods and statements by providing an option for fairness, providing a non-blocking attempt to acquire a lock (tryLock()), an attempt to acquire the lock that can be interrupted (lockInterruptibly(), and an attempt to acquire the lock that can timeout (tryLock(long, TimeUnit)).
    • Fairness- ReentrantLock class in Java has one constructor which takes boolean value as an argument. That lets you choose whether you want a fair or an unfair lock depending upon whether the boolean value is true or false. A fair lock is one where the threads acquire the lock in the same order they asked for it; whereas in case of an unfair lock a thread can sometimes acquire a lock before another thread that asked for it first.
      With Synchronized there is no such option.
    • Lock interruptibly- ReentrantLock provides a method lockInterruptibly
      public void lockInterruptibly() throws InterruptedException
      
      Where the thread acquires a lock if it is not interrupted.
    • Ability to check if the lock is being held- ReentrantLock provides ability to check if the lock is already being held using tryLock() method. This provides a non-blocking attempt to acquire a lock for a thread.

      tryLock()- Acquires the lock only if it is not held by another thread at the time of invocation.

      tryLock(long timeout, TimeUnit unit)- Acquires the lock if it is not held by another thread within the given waiting time and the current thread has not been interrupted.

  5. There are some other features provided by ReentrantLock-
    • getHoldCount()- Queries the number of holds on this lock by the current thread.
    • getWaitingThreads(Condition condition)- Returns a collection containing those threads that may be waiting on the given condition associated with this lock.
    • isHeldByCurrentThread()- Queries if this lock is held by the current thread.
    • isLocked()- Queries if this lock is held by any thread.

That's all for this topic Difference Between ReentrantLock and Synchronized in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Java StampedLock With Examples
  2. Callable and Future in Java With Examples
  3. AtomicInteger in Java With Examples
  4. Lock Striping in Java Concurrency
  5. Java Concurrency Interview Questions And Answers

You may also like-

  1. Deadlock in Java Multi-Threading
  2. Java ThreadLocal Class With Examples
  3. How to Sort Elements in Different Order in TreeSet
  4. Optional Class in Java With Examples
  5. Functional Interface Annotation in Java
  6. Interface Static Methods in Java
  7. Method Overriding in Java
  8. Dependency Injection in Spring Framework

Thursday, July 8, 2021

Java StampedLock With Examples

In Java 8 a new kind of lock StampedLock is added which apart from providing separate read and write locks also has a feature for optimistic locking for read operations. StampedLock in Java also provides method to upgrade read lock to write lock which is not there in ReentrantReadWriteLock in Java.

The locking methods of StampedLock in Java return a stamp represented by a long value. You can use these stamps to either release a lock, to check if the lock is still valid, to convert a lock.

So, if you want to use a StampedLock for acquiring a write lock it can be done as-

StampedLock sl = new StampedLock();
//acquiring writelock
long stamp =  sl.writeLock();
try{
 ...
 ...
}finally {
 //releasing lock
 sl.unlockWrite(stamp);
}