작성
·
170
0
먼저 강의 잘 듣고 있습니다.
강의 자료 202쪽에 보면 아래 그림과 같이 ReentrantLock.lockInterruptibly() 예제 코드가 작성되어 있는데요.
이 코드를 강의 소스코드 (LockInterruptiblyExample.java) 에 적용해 보았습니다. 적용한 코드는 아래와 같습니다.
public class LockInterruptiblyExample {
public static void main(String[] args) {
Lock lock = new ReentrantLock();
Thread thread1 = new Thread(() -> {
try {
lock.lockInterruptibly(); // 락을 시도하며, 인터럽트가 들어오면 중단
System.out.println("스레드 1이 락을 획득했습니다");
} catch (InterruptedException e) {
System.out.println("스레드 1이 인터럽트를 받았습니다");
} finally {
lock.unlock();
System.out.println("스레드 1이 락을 해제했습니다");
}
});
Thread thread2 = new Thread(() -> {
try {
lock.lockInterruptibly(); // 락을 시도하며, 인터럽트가 들어오면 중단
try {
System.out.println("스레드 2가 락을 획득했습니다");
} finally {
lock.unlock();
System.out.println("스레드 2가 락을 해제했습니다");
}
} catch (InterruptedException e) {
System.out.println("스레드 2가 인터럽트를 받았습니다");
}
});
thread1.start();
thread2.start();
thread1.interrupt();
// thread2.interrupt();
try {
Thread.sleep(500);
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
이 코드를 실행했을 때, 아래 이미지와 같이 IllegalMonitorStateException 이 발생했는데요.
아마 try ~ catch ~ finally 블록에 의한 문제가 아닐까 싶습니다. 이 부분이 어떻게 동작하여 오류가 발생한 건지 궁금한데, 답변 해주시면 감사하겠습니다.
답변 1
0
네
위 코드에서 IllegalMonitorStateException
가 발생하는 원인은 unlock
메서드가 락을 획득하지 않은 스레드에 의해 호출되기 때문인데요
ReentrantLock
객체의 unlock
메서드는 락을 획득한 스레드만이 호출할 수 있습니다.
위 코드에서는 thread1
이 인터럽트될 때 락을 획득하지 않은 상태에서 thread1
이 finally 에서unlock
을 호출하게 되어 예외가 발생하고 있습니다.
그래서 다음과 같이 할 수 있습니다.
Thread thread1 = new Thread(() -> {
try {
lock.lockInterruptibly(); // 락을 시도하며, 인터럽트가 들어오면 중단
System.out.println("스레드 1이 락을 획득했습니다");
} catch (InterruptedException e) {
System.out.println("스레드 1이 인터럽트를 받았습니다");
} finally {
if (((ReentrantLock) lock).isHeldByCurrentThread()) {
lock.unlock();
System.out.println("스레드 1이 락을 해제했습니다");
}
}
});
즉 finally 에서 현재 스레드가 락을 획득한 경우에만 unlock 을 호출하도록 하는 것입니다.
thread1 이 lock.lockInterruptibly() 을 호출하기 전에 인터럽트 되었고, 곧바로 finally블록을 수행하면서 unlock을 시도(lock획득 안한 상태)하기 때문에 Exception이 발생한 것으로 이해했습니다.
답변 감사드립니다!