Reputation: 1470
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.
Upvotes: 2
Views: 3741
Reputation: 2626
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();
}
}
Upvotes: 3