[CS/운영체제] 멀티스레드와 동시성 - 16부

황제연·2025년 7월 9일
1

CS학습

목록 보기
130/193
post-thumbnail

스레드의 대기

synchronized와 ReentrantLock의 대기상태에 대해 알아보겠습니다

synchronized 대기

synchornized의 대기상태는 두가지 경우가 있습니다
먼저 BLOCKED 상태로 락 획득을 대기하고 synchornized를 시작할 때 락이 없으면 대기합니다
다른 스레드가 synchronized를 빠져나갈 때 대기가 풀리며 락 획득을 시도합니다

또한 WAITING 상태로 대기하는 경우도 이습니다
wait()를 호출했을 때 스레드 대기 잡합에서 대기하고 다른 스레드가 notify()를 호출했을 때
빠져나갑니다

락 대기 집합

락을 기다리는 스레드가 여러개라면 그 스레드에 대해서 어디선가 관리되고 있어야 합니다
사실 락 획득을 대기하기 위해 BLOCKED되는 경우 락 대기 집합이라는 곳에서 대기하고 있습니다

스레드 대기 집합에 있는 특정 스레드가 큐에서 데이터를 확인하기 위해 락을 획득하고
다른 스레드들은 락 대기 집합에서 락을 획득할 떄까지 대기합니다
큐에 데이터가 없으면 락을 반납하고 다시 획득하고를 반복하며, 다시 스레드 대기 집합으로 돌아가고
생산자 스레드에 의해 데이터가 채워지면 위 과정중 한 스레드가 작업을 완료합니다

멀티스레드와 임계영역을 위한 3가지 기본요소

자바의 모든 객체 인스턴스는 멀티스레드와 임계영역을 다루기 위해
내부에 3가지 기본 요소를 가집니다

  • 모니터 락
  • 락 대기 집합 (모니터 대기 집합)
  • 스레드 대기 집합
    락 대기 집합 -> 스레드 대기 집합 순으로 대기하고 있으며,
    다시 역순으로 빠져나와서 임계영역을 수행합니다

각 요소는 서로 맞물려서 돌아갑니다
synchronized를 사용한 임계영역에 들어가려면 모니터락이 필요하며
모니터 락이 없으면 락 대기 집합에 들어가서 BLOCKED 상태로 락을 기다립니다

모니터 락을 반납하면 락 대기 집합에 있는 스레드 중 하나가 락을 획득하고 BLOCKED -> RUNNABLE 상태가 됩니다

마찬가지로 wait()을 호출해서 스레드 대기 집합에 들어가기 위해서는 모니터락이 필요합니다
스레드 대기 집합에 들어가면 모니터락을 반납하며
스레드가 notify()를 호출하면 스레드 대기 집합에 있는 스레드 중 하나가 스레드 대기 집합을 빠져나옵니다
그리고 모니터 락 획득을 시도하며 획득하면 임계영역을 수행하고
획득하지 못하면 락 대기 집합에 들어가서 BLOCKED 상태로 락을 기다립니다

ReentrantLock의 대기

ReentrantLock도 마찬가지로 2가지 단계의 상태가 존재합니다

단계

이번에는 ReentrantLock의 대기 큐에서 관리합니다
WAITING 상태로 락 획득을 대기하며, lock.lock()을 호출했을 때 락이 없으면 대기합니다
다른 스레드가 lock.unlock()을 호출했을 때 대기가 풀리며 락 획득을 시도하고
락을 획득하면 대기 큐를 빠져나갑니다

Condition.await()을 호출했을 때, condition 객체의 스레드 대기 공간에서 관리하며
WAITING 상태로 대기하고 다른 스레드가 condition.signal()을 호출했을 때
condition 객체의 스레드 대기 공간에서 빠져나갑니다

2단계 대기소

참고로 ReentrantLock도 2단계 대기소가 되어있습니다
condition 객체의 스레드 대기 공간을 빠져나온다고 바로 실행되는 것은 아니며
임계영역 안에서 항상 락이 있는 하나의 스레드만 실행될 수 있습니다

ReentrantLock의 락을 획득해야 RUNNABLE 상태가 되며 그 다음 코드를 실행할 수 있고,
락을 획득하지 못하면 WAITING 상태로 락을 획득할 때까지 ReentrantLock의 대기 큐에 대기합니다

참고

  • 김영한의 실전 자바 - 고급 1편
profile
Software Developer

0개의 댓글