2

I'm unable to make out the difference. I read this: actual-use-of-lockinterruptibly-for-a-reentrantlock

and wanted to test it. Here goes the code:

public class Test {
public static void main(String[] args){
    Test test = new Test();
    test.inturreptWork();
    //Main group
    System.out.println("Main Thread group: "+Thread.currentThread().getThreadGroup().getName());
    //System group  is the parent of main group. it contains system level threads like finalizer,signal dispatcher,attach listener
    System.out.println("Main Thread group: "+Thread.currentThread().getThreadGroup().getParent());
}

public void inturreptWork(){
    Inturrept inturrept= new Inturrept();
    Thread t1 = new Thread(inturrept,"Thread 1");
    Thread t2 = new Thread(inturrept,"Thread 2");
    Thread t3 = new Thread(inturrept,"Thread 3");
    try{
    t1.start();
    Thread.sleep(1000);
    t2.start();
    Thread.sleep(1000);
    t2.interrupt();
    t3.start();
    t1.join();
    t2.join();
    t3.join();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    finally {
        System.out.println("Finally");
    }


}

Here is the Inturrept Class

        public class Inturrept implements Runnable {
    Lock lock = new ReentrantLock();

    @Override
    public void run() {
        try {
            System.out.println("Trying to get lock ,Thread name is: " + Thread.currentThread().getName());
            lock.lock();// or   lock.lockInterruptibly();

            System.out.println("Running");
            Thread.sleep(7000);// Use something else to mimic sleep as it throws interrupted exception 
            lock.unlock();// This caused IllegalMonitorStateException 
        } catch (InterruptedException e) {
            System.out.println("I was inturrepted, Thread name is: " + Thread.currentThread().getName());
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

Console Output:

Trying to get lock ,Thread name is: Thread 1
Running
Trying to get lock ,Thread name is: Thread 2
Trying to get lock ,Thread name is: Thread 3
Running
Exception in thread "Thread 1" I was inturrepted, Thread name is: Thread 2
java.lang.IllegalMonitorStateException
    at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:151)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1261)
    at java.util.concurrent.locks.ReentrantLock.unlock(ReentrantLock.java:457)
    at com.test.main.Inturrept.run(Inturrept.java:21)
    at java.lang.Thread.run(Thread.java:748)
java.lang.InterruptedException: sleep interrupted
    at java.lang.Thread.sleep(Native Method)
    at com.test.main.Inturrept.run(Inturrept.java:15)
    at java.lang.Thread.run(Thread.java:748)
Running
Exception in thread "Thread 3" Finallyjava.lang.IllegalMonitorStateException
    at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:151)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1261)
    at java.util.concurrent.locks.ReentrantLock.unlock(ReentrantLock.java:457)
    at com.test.main.Inturrept.run(Inturrept.java:21)
    at java.lang.Thread.run(Thread.java:748)

Main Thread group: main
Main Thread group: java.lang.ThreadGroup[name=system,maxpri=10]

As mentioned in the answer "This is the same as with regular lock(). But if another thread interrupts the waiting thread lockInterruptibly() will throw InterruptedException." Even if it's lock.lock() or lock.lockinterruptibly(). The thread gets interrupted. so what's the difference? did i understand something wrong please assist. Also another question I've is why do I see "Exception in thread "Thread 3" in console. It ran as I can see two "runnings" in logs.

Thanks you.

Kid101
  • 1,440
  • 11
  • 25
  • It's the `sleep` that throws the `InterruptedException`, not the `lock`. When you `interrupt` the `Thread`, it sets its `interrupted` flag and leaves it there. When your thread finally acquires the lock, it's in this interrupted state and tries to `sleep`. `sleep` throws an `InterruptedException` _if any thread has interrupted the current thread._ – Sotirios Delimanolis Jun 18 '17 at 15:43
  • Also, please move the `lock()` call outside the `try` and remove the `unlock()` inside the `try` block. – Sotirios Delimanolis Jun 18 '17 at 15:46
  • @SotiriosDelimanolis I used the lock method inside the try because I was using lockInterruptibly as well.Yes I removed the unlock inside the try, my bad which was giving a IllegalMonitorStateException exception. Also it was wrong to use thread.sleep() to check if lockInterruptibly actually throws interrupted exception. because when I interrupted the thread, it set the interrupted flag to true making sleep to wake up clear the flag and send throw the interrupted exception. as result I wasn't able to make out if lockInterruptibly actually threw the InterruptedException. If someone else comes by – Kid101 Jun 18 '17 at 19:00
  • long now = System.currentTimeMillis(); Date d= new Date(Calendar.getInstance().getTimeInMillis()+5000); while(now < d.getTime()){ now=System.currentTimeMillis(); } something like this to mimic sleep. – Kid101 Jun 18 '17 at 19:00

1 Answers1

2

lockInterruptibly() first check if thread is interrupted or not.If interrupted then throw InterruptedException

 if (Thread.interrupted())
            throw new InterruptedException();
        if (!tryAcquire(arg))
            doAcquireInterruptibly(arg);

lock.unlock() is calling twice in your code .so it is throwing IllegalMonitorStateException because not same thread is doing unlock.When the thread do the unlock without lock it throw the exception.

 if (Thread.currentThread() != getExclusiveOwnerThread())
                throw new IllegalMonitorStateException();

Thread.sleep causing the interrupt exception.Sleep method throw InterruptedException

void sleep(long millis) throws InterruptedException

Modified code

 public void run() {
try {
    System.out.println("Trying to get lock ,Thread name is: " + Thread.currentThread().getName());
    lock.lock();
    System.out.println("Running");
    //Thread.sleep(7000);

} catch (Exception e) {
    System.out.println("I was inturrepted, Thread name is: " + Thread.currentThread().getName());
    e.printStackTrace();
} finally {
    lock.unlock();
}

}

gati sahu
  • 2,576
  • 2
  • 10
  • 16