Tôi muốn thay thế khối syncronized
bằng ReentrantLock
để hỗ trợ gián đoạn chờ khóa. Đối với điều này, tôi sử dụng phương pháp lockInterruptibly()
và thử thành ngữ/khối finally:Cách tránh IllegalMonitorStateException khi sử dụng lockInterruptibly trên Reentrantlock
private ReentrantLock lock = new ReentrantLock();
try
{
lock.lockInterruptably();
}
catch(InterruptedException e)
{
Thread.currentThread.interrupt();
}
finally
{
lock.unlock();
}
Vấn đề là cuối cùng cũng ofcourse cũng xảy ra khi InterruptedException xảy ra. Điều này dẫn đến một số IllegalMonitorStateException
, bởi vì khóa không được giữ bởi luồng hiện tại.
chương trình đơn giản này chứng tỏ điều này:
public class LockTest
{
public static void main(String[] args)
{
System.out.println("START");
Thread interruptThread = new Thread(new MyRunnable(Thread.currentThread()));
interruptThread.start();
ReentrantLock lock = new ReentrantLock();
Thread takeLockThread = new Thread(new TakeLockRunnable(lock));
takeLockThread.start();
try
{
Thread.sleep(500);
System.out.println("Trying to take lock on thread " + Thread.currentThread().getName());
lock.lockInterruptibly();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
finally {
lock.unlock();
}
System.out.println("DONE");
}
private static class MyRunnable implements Runnable
{
private Thread m_thread;
private MyRunnable(Thread thread)
{
m_thread = thread;
}
@Override
public void run()
{
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
// ignore
}
System.out.println("Interrupting thread " + m_thread.getName());
m_thread.interrupt();
}
}
private static class TakeLockRunnable implements Runnable
{
private ReentrantLock m_lock;
public TakeLockRunnable(ReentrantLock lock)
{
m_lock = lock;
}
@Override
public void run()
{
try
{
System.out.println("Taking lock on thread " + Thread.currentThread().getName());
m_lock.lock();
Thread.sleep(20000);
}
catch (Exception e)
{
e.printStackTrace();
}
finally {
m_lock.unlock();
}
}
}
}
It in sản lượng này:
START Taking lock on thread Thread-1 Trying to take lock on thread main java.lang.InterruptedException at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireInterruptibly(AbstractQueuedSynchronizer.java:877) at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1201) at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:312) at LockTest.main(LockTest.java:25) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120) Exception in thread "main" java.lang.IllegalMonitorStateException at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:127) at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1239) at java.util.concurrent.locks.ReentrantLock.unlock(ReentrantLock.java:431) at LockTest.main(LockTest.java:32) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120) Interrupting thread main
Bất kỳ ý tưởng về những gì cách tốt nhất là để tránh điều này?
bất kỳ ai quan tâm để nhận xét về downvote? – jtahlborn
Lần đầu tiên tôi sử dụng 'isHeldByCurrentThread', nhưng sau khi đọc tất cả các nhận xét, tôi nghĩ phiên bản này là phiên bản duy nhất thực sự chính xác. –
@WimDeblauwe mà bạn đang đề cập đến, và tại sao bạn nghĩ rằng sử dụng 'isHeldByCurrentThread' là không chính xác? –