문제1.

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();
    }
}
  1. 결과를 예측해보자 0

  2. lock이 static으로 정의된 경우 부모 클래스와 자식 클래스는 동일한 lock을 사용할까?

→ static으로 정의된 경우는 클래스 단위의 lockd으로 확장되고, 아닌경우에는 인스턴스의 락의 단위로만 lock설정이 된다.

문제2.

<aside> ✨ 1) Lock 재진입의 필요한 상황과 주의점에 대해 서술 2) ReadWriteLock의 필요성 3) ReadWriteLock을 사용하는 상황에서 ReadLock을 가진 쓰레드가 공유자원에 접근해 있는 상황에서 WriteLock을 가진 쓰레드가 임계영역에 접근을 시도할 때의 동작 (다른 ReadLock을 가진 쓰레드들도 임계영역에 진입을 시도하고 있다)

</aside>

  1. 재진입을 시도한 lock 수만큼 unlock을 수행해 줘야한다. stack처럼 lock이 쌓이기 때문 +) 대체로 재진입은 lock을 획득한 상태에서 다시 lock을 획득하는 경우를 말한다.
  2. writer 가 쓰기 작업 동안에 공유 DB에 대해 배타적 접근 권한을 가지게 할 필요가 있는데, 이 때 두 가지의 문제를 고려하는 ReadWriteLock 이 필요하다.
    1. 어느 reader도 다른 reader 를 기다려서는 안 된다. → writer가 기다리고 있기 때문에, 다른 reader들이 끝날 때 까지 기다리는 reader 가 있어서는 안 된다 ⇒ writer가 기아 상태에 빠지는 경우
    2. writer 가 객체에 접근하려고 기다리고 있다면, 새로운 reader 들은 읽기를 시작하지 못하는 경우 ⇒ reader 가 기아상태에 빠지는 경우
  3. 만약 readlock을 가진 스레드가 하나인 경우에는 락을 반환하고 writerLock을 가진 스레드를 실행하지만, 1개 이상의 readLock이 있을 시에는 readLock을 가진 스레드 먼저 모두 실행 시킨 후 writerLock을 사용한다.

⇒ 읽기 와 쓰기 관점에 따라 달리진다

문제3.

<aside> ✨ 식사하는 철학자 문제에서 발생하는 문제점과 해결책에 대해 서술

</aside>

  1. 젓가락이 두 개 있어야 먹을 수 있다 → 세마포를 사용하여, 2개 인 것을 확인 : 그러나 양옆이 동시해 수행시 교착상태에 빠질 수 있음
  2. 양 옆 사람이 젓가락을 사용하는 경우 → 철학자는 반드시 자기 기준 왼쪽 젓가락을 집고 그 후 반대쪽 젓가락을 집는다는 것을 가정하에, 조건 변수를 거는 방법으로 교착상태를 해결할 수 있으나, 굶어죽는 철학자가 생길 수 있따.

+) 코드가 락을 갖고 수행중 타임슬라이스가 끝나 준비큐로 돌아갈 떄 락을 같이 갖고 이동하여 준비큐에서 자기 순서가 됐을 때 락 경쟁 없이 바로 수행한다(finally가 수행되지 않음 → 코드가 거까지 수행되지 않았기 떄문이다.)