import java.util.concurrent.locks.ReentrantLock;
class Parent {
protected final ReentrantLock lock = new ReentrantLock();
protected int sharedResource = 0;
public void increment() {
lock.lock();
try {
System.out.println("Parent incrementing");
sharedResource++;
System.out.println("Parent incremented: " + sharedResource);
} finally {
lock.unlock();
}
}
}
class Child extends Parent {
public void decrement() {
lock.lock();
try {
System.out.println("Child decrementing");
sharedResource--;
System.out.println("Child decremented: " + sharedResource);
} finally {
lock.unlock();
}
}
}
public class Example {
public static void main(String[] args) {
Child child = new Child();
Thread t1 = new Thread(() -> {
for (int i = 0; i < 5; i++) {
child.increment();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 5; i++) {
child.decrement();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
t1.start();
t2.start();
}
}
결과를 예측해보자 0
lock이 static으로 정의된 경우 부모 클래스와 자식 클래스는 동일한 lock을 사용할까?
→ static으로 정의된 경우는 클래스 단위의 lockd으로 확장되고, 아닌경우에는 인스턴스의 락의 단위로만 lock설정이 된다.
<aside> ✨ 1) Lock 재진입의 필요한 상황과 주의점에 대해 서술 2) ReadWriteLock의 필요성 3) ReadWriteLock을 사용하는 상황에서 ReadLock을 가진 쓰레드가 공유자원에 접근해 있는 상황에서 WriteLock을 가진 쓰레드가 임계영역에 접근을 시도할 때의 동작 (다른 ReadLock을 가진 쓰레드들도 임계영역에 진입을 시도하고 있다)
</aside>
⇒ 읽기 와 쓰기 관점에 따라 달리진다
<aside> ✨ 식사하는 철학자 문제에서 발생하는 문제점과 해결책에 대해 서술
</aside>
+) 코드가 락을 갖고 수행중 타임슬라이스가 끝나 준비큐로 돌아갈 떄 락을 같이 갖고 이동하여 준비큐에서 자기 순서가 됐을 때 락 경쟁 없이 바로 수행한다(finally가 수행되지 않음 → 코드가 거까지 수행되지 않았기 떄문이다.)