'Actual use of lockInterruptibly for a ReentrantLock

What do you actually use for this method lockInterruptibly? I have read the API however it's not very clear to me. Could anybody express it in other words?



Solution 1:[1]

lockInterruptibly() may block if the the lock is already held by another thread and will wait until the lock is aquired. This is the same as with regular lock(). But if another thread interrupts the waiting thread lockInterruptibly() will throw InterruptedException.

Solution 2:[2]

Try to understand this concept through below code example.

Code Sample:

package codingInterview.thread;

import java.util.concurrent.locks.ReentrantLock;

public class MyRentrantlock {

    Thread t = new Thread() {

        @Override
        public void run() {

            ReentrantLock r = new ReentrantLock();
            r.lock();

            System.out.println("lock() : lock count :" + r.getHoldCount());

            interrupt();
            System.out.println("Current thread is intrupted");
            r.tryLock();
            System.out.println("tryLock() on intrupted thread lock count :" + r.getHoldCount());
            try {
                r.lockInterruptibly();
                System.out.println("lockInterruptibly() --NOt executable statement" + r.getHoldCount());
            } catch (InterruptedException e) {
                r.lock();
                System.out.println("Error");
            } finally {
                r.unlock();
            }

            System.out.println("lockInterruptibly() not able to Acqurie lock: lock count :" + r.getHoldCount());

            r.unlock();
            System.out.println("lock count :" + r.getHoldCount());
            r.unlock();
            System.out.println("lock count :" + r.getHoldCount());

        }

    };

    public static void main(String str[]) {
        MyRentrantlock m = new MyRentrantlock();
        m.t.start();

        System.out.println("");
    }

}

Output:

lock() : lock count :1
Current thread is intrupted
tryLock() on intrupted thread lock count :2
Error
lockInterruptibly() not able to Acqurie lock: lock count :2
lock count :1
lock count :0

Solution 3:[3]

Based on Evgeniy Dorofeev's answer, I just deliberately come up with such demo but I really I have no clue where is exactly, it could be used. Perhaps this demo could help a tad :)

private static void testReentrantLock() {
    ReentrantLock lock = new ReentrantLock();
    Thread thread = new Thread(() -> {
        int i = 0;
        System.out.println("before entering ReentrankLock block");
        try {
            lock.lockInterruptibly();
                while (0 < 1) {
                    System.out.println("in the ReentrankLock block counting: " + i++);
                }
        } catch (InterruptedException e) {
            System.out.println("ReentrankLock block interrupted");
        }
    });
    lock.lock(); // lock first to make the lock in the thread "waiting" and then interruptible
    thread.start();
    thread.interrupt();
}

Output

before entering ReentrankLock block
ReentrankLock block interrupted

Solution 4:[4]

A thread that uses lockInterruptibly() can be interrupted by another thread. So, invocation to lockInterruptibly() throws InterruptedException which can be caught, and useful stuff can be done within the catch block like releasing the held lock, so that the other thread that has caused the interrupt to happen can gain access to the released lock. Think of the case where you have a common data structure with the below read and write constraints:

  1. A single thread is responsible for writing to the common data structure.
  2. There is a single reader thread.
  3. When a write is in process, read should not be allowed.

To fulfil the above constraints, the reader thread can use lockInterruptibly() to gain access to the java.util.concurrent.locks.ReentrantLock. That means the reader thread can be interrupted any time amidst processing by the writer thread. Writer thread would have access to the reader thread instance, and writer can interrupt the reader. When the reader receives the interrupt, in the catch block of the InterruptedException, the reader should unlock the hold on the ReentrantLock and await notification from the writer thread to proceed further. The writer thread can acquire the same lock using tryLock method. Code snippet for the reader and writer threads is given below:

Common fields accessed by both reader and writer threads:

ReentrantLock commonLock = new ReentrantLock(); //This is the common lock used by both reader and writer threads.
List<String> randomWords = new ArrayList(); //This is the data structure that writer updates and reader reads from. 
CountDownLatch readerWriterCdl = new CountDownLatch(1); //This is used to inform the reader that writer is done.

Reader:

try {
        if(!commonLock.isHeldByCurrentThread())
            commonLock.lockInterruptibly();                     
         System.out.println("Reader: accessing randomWords" +randomWords);              
    } catch (InterruptedException e) {                      
            commonLock.unlock();
            try {
                    readerWriterCdl.await();
                } 
                catch (InterruptedException e1) {

                }
    }

Writer:

if(commonLock.isLocked() && !commonLock.isHeldByCurrentThread()) 
{

    readerThread.interrupt();
}
                        
boolean lockStatus = commonLock.tryLock();
if(lockStatus) {
   //Update the randomWords list and then release the lock.
   commonLock.unlock();
   readerWriterCdl.countDown();
   readerWriterCdl = new CountDownLatch(1);
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Evgeniy Dorofeev
Solution 2 jatin Goyal
Solution 3 Hearen
Solution 4